﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using csLTDMC;
using DMC300Axis_IO.Function;
using LitJson;
using MvCameraControl;
using OCR.Config;
using OCR.Function;
using OCR.SystemThread;
using OCR.SettingsForm;
using OCR.Algorithm;
using System.Collections.Concurrent;
using System.Globalization;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Engines;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Drawing.Imaging;
using OpenCvSharp;
using System.Runtime.InteropServices;
using System.Timers;
using System.Diagnostics;

namespace OCR
{
    public partial class OCR_Form : Form
    {
        public static Camera_Form camera_Form;
        public static Template_Form template_Form;
        public static Param_Form param_Form;
        public static OCR_Form oCR_Form;
        public static PCI1616IO_Form pCI1616IO_Form;
        public static MultipleRectTemplate_Form multipleRectTemplate_Form;
        public static ProductTemplateConfig_Form ProductTemplateConfig_Form;

        public static bool isSaveImg;
        public static bool isSaveImg_PLC;

        public static ModbusModule modbusModule = new ModbusModule();

        bool isLocalTest;

        bool isConfigList;

        public OCR_Form()
        {
            InitializeComponent();

            InitializeTimers();
            RegisterHotKeys();

            HideBorder();

            Console.OutputEncoding = Encoding.UTF8;

            AlgorithmModule_GPU.CreateInstance();

            AlgorithmModule_GPU.ImageHandleV2_ByteArray(Application.StartupPath + "\\TemplateInput\\TestFirst.bmp");


            LocalInfo.LocalInfoInitial();


            isConfigList = true;
            if (isConfigList)
            {
                //读取清单
                SetProductConfigListName_Config();

                //LocalTemplateList_Config.CreateDefault();

                //获取清单信息
                LocalTemplateList_Config.LocalTemplateSingleInfosInitial(LocalInfo.ProductConfigListName);
            }

            LocalTemplateSingleInfos_Config.LocalTemplateSingleInfosInitial();


            SetTemplateImgPath_Config();
            SetTem_RectMaxCount_Config();

            SetSofrwareType();

            #region   初始化控件缩放

            x = Width;
            y = Height;
            setTag(this);

            #endregion

            Console.WriteLine("------大小------"+ FormatSize(GetFolderSize("ImageResultFiles"))); 
        }
        //mainCameraPb的初始位置
        private System.Drawing.Point PicStartPos;
        //mainCameraPb的初始大小
        private System.Drawing.Size PicSize;
        //鼠标滚轮缩放图片的增量值
        private int ZoomStep = 40;

        public bool isMainCameraPbWheel;
        private void mainCameraPb_MouseWheel(object sender, MouseEventArgs e)
        {
            if (mainCameraPb.Image == null) return;
            //if (!isMainCameraPbWheel) return;

            PictureBox pbox = mainCameraPb;
            int x = e.Location.X;
            int y = e.Location.Y;
            int ow = pbox.Width;
            int oh = pbox.Height;
            int VX, VY;  //因缩放产生的位移矢量
            if (e.Delta > 0) //放大
            {
                //第1步
                pbox.Width += ZoomStep;
                pbox.Height += ZoomStep;
                //第2步
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                //第3步
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;

                //Console.WriteLine(string.Format("宽：{0}，高：{1}",pbox.Width,pbox.Height));
            }
            if (e.Delta < 0) //缩小
            {
                if (pbox.Width < 1200)
                {
                    ReturnManiCameraPb();
                    return;
                }
                //防止一直缩成负值
                //if (pbox.Width < 1100)
                //    return;

                pbox.Width -= ZoomStep;
                pbox.Height -= ZoomStep;
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                 BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;
            }

            //第4步，求因缩放产生的位移，进行补偿，实现锚点缩放的效果
            VX = (int)((double)x * (ow - pbox.Width) / ow);
            VY = (int)((double)y * (oh - pbox.Height) / oh);
            pbox.Location = new System.Drawing.Point(pbox.Location.X + VX, pbox.Location.Y + VY);
        }
        public void ReturnManiCameraPb()
        {

            if (mainCameraPb != null && mainCameraPb.Image != null)
            {
                mainCameraPb.Image = mainCameraPb.Image;
                //设置坐标
                mainCameraPb.Location = PicStartPos;
                mainCameraPb.Size = PicSize;
            }
        }
        public void ReturnManiCameraPb(Bitmap bitmap)
        {
 
            if (mainCameraPb != null && mainCameraPb.Image != null)
            {
                mainCameraPb.Image = bitmap;
                //设置坐标
                mainCameraPb.Location = PicStartPos;
                mainCameraPb.Size = PicSize;
            }
        }
        private void OCR_Form_Load(object sender, EventArgs e)
        {
           
            oCR_Form = this;
            Console.WriteLine(AlgorithmModule_GPU.FilterWithLINQ("Hello 你好 123!@# /世界 abc/456"));


            mainCameraPb.SizeMode = PictureBoxSizeMode.Zoom;
            mainCameraPb.BackgroundImageLayout = ImageLayout.Zoom;

            //string encryptedBase64 = "Esd9Bkon7R8isutC2MtIpCE4xCsTOS+YEnBLSZCFiSN+fFPdj64iXhefzRfrtzThhmUPLY4ofYcvURcUw9goArk8UVsKHH/ItvyglJZhlipSYOM9q4MfpUnNe1GUedr55KtDGO6U6zUBKygv1x/zI1To9RFxzXOyEFV2uHMks/E=";
            //string publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmXsT7fxmz4sKAVIgNjUe5ulTveodnyMuPBqkBmj1aN7yUojbAhhUn0pNMAWlZhf5BzKy7DROSlcFIONt8MZ9505xRdFEUsFHhlFxLsf9ygRMMNJ8XZ1mD7NC8Gq6ee8YOpNg9CJK/5WFOurM1QWW8si+wGvMzGjd3wVH7orgrEwIDAQAB";
            //Console.WriteLine("decryptedBytes:---------------" + DecryptPublicKeyJava1(publicKey, encryptedBase64));

            PicStartPos = mainCameraPb.Location;
            PicSize = mainCameraPb.Size;
            this.mainCameraPb.MouseWheel += new MouseEventHandler(this.mainCameraPb_MouseWheel);


            Console.WriteLine("softwareType:  "+softwareType);

            LocalInfo.lastDI_DT = DateTime.Now;
            LocalInfo.CameraStateResult = string.Empty;

            //DeleteDay1Rb.Checked = true;
            SetDeleteDay();

            //LocalInfo.outImgPath = Application.StartupPath + "\\out\\";
            SetOutImgPath();
            SaveImgPathTB.Text = LocalInfo.outImgPath;

            //int deleteCount = GetEarliestRangeFolders(LocalInfo.outImgPath, LocalInfo.deleteDay);
            //Console.WriteLine($"找到最远 {DiskSpaceManager.GetOldestFolders(LocalInfo.outImgPath, deleteCount).Count} 个待删除文件夹");
            //Console.WriteLine($"除去最近 {DiskSpaceManager.GetNonRecentFoldersByTime(LocalInfo.outImgPath, LocalInfo.deleteDay).Count} 个待删除文件夹");

            LocalInfo.PermissionIndex = 0;
            SetPermissionType();

            SetDI_Interval();

            SetLocalTemplateInfos();

            SetIsLOG_Config();

            SetProductCount_Config();

            SetLocalTemplateInfoPanel();

            SetCameraSerialNumber_Config();

            SetCameraSerialNumGB();

            SetNgOrOkSignal();

            SetIsStartRunConfig();

            SetCloseSignalDelayTime_Config();

            SetNGControlType_Config();

            SetRepeatSignalCheckTime_Config();

            SetisOKRect_Config();

            SetCheckDI_Config();

            SetisSaveOK_Config();

            SetisSaveNG_Config();

            //开启相机
            CameraReceiveThread.CameraInitialize();

            isLocalTest = true;

            //TestSaveImg_IO1();
            //TestSaveImg_IO2();

            if (softwareType == "0")
            {
                //Initial_Card.DMC300_InitialClass();
                //DIO_Thread.DIO_State();                                          //DIO线程启动
                PCI1616_Initial.PCI1616_InitialClass();
                IOThread_Run.DIO_State();                                          //IO卡线程启动
                CameraTriggerThread.CameraTrigger_Thread();                      //相机DIO触发取像线程启动
                NG_Control.NG_Flow_Thread();
                Console.WriteLine("LocalInfo.NGControlType:-----"+LocalInfo.NGControlType);
                if (LocalInfo.NGControlType == "0")
                    NGControlThread.NGControl_Thread();
                runStateTimer.Start();
                CameraTriggerThread.iCameraTrigger_Step = 1;
                //CameraTriggerThread_Template.CameraTrigger_Thread();
                CameraTriggerThread_ModbusRealTime.CameraTrigger_Thread();
                CameraTriggerThread_MultiTemplate.CameraTrigger_Thread();

                CreateFolderThread.CreateFolder_Thread();

                StartUpdateUIThreads();
                DiskSpaceThread.CheckDiskSpace_Thread();
                CameraReceiveRealTimeThread.CameraReceiveRealTime_Thread();

                SendIO_NGThread_All.SendIO_NG_Thread();

                CameraOnlineThread.CheckCameraOnline_Thread();
                CameraRestartThread.CheckCameraRestart_Thread();

                CameraSingleTriggerThread.CameraSingleTrigger_Thread();

                //DelayNgSingleThread.DelayNgSingle_Thread();
                //OutputDelayNgSingleThread.OutputDelayNgSingle_Thread();

                //DIRecordThread.DIRecord_Thread();

                //DMC300_Info.NGDelay = ushort.Parse("10");              //一开始就将延迟NG吹气时间设定进去
                //DMC300_Info.NG_Action = ushort.Parse("50");            //一开始就将NG吹气动作时间设定进去
                //DMC300_Info.CameraTrigger_Delay = ushort.Parse("10");  //一开始就将相机外部触发延迟时间设定进去
                //DMC300_Info.CameraTrigger_Time = ushort.Parse("30");   //一开始就将相机外部触发动作时间设定进去

                //Console.WriteLine(LTDMC.dmc_read_sevon_pin(DMC300_Info.usCardId[0], 0));
                //if (LTDMC.dmc_read_sevon_pin(DMC300_Info.usCardId[0], 0) == 1)      //當讀取狀態為1時，當下始能未開啟
                //{
                //    LTDMC.dmc_write_sevon_pin(DMC300_Info.usCardId[0], 0, 0);       //下達0時是開啟始能
                //}
                if (isLocalTest)
                {
                    TestSetInfoThread.TestSetInfo_Thread();
                    //TestNGControlThread.TestNGControl_Thread();
                }


                Console.WriteLine("LocalInfo.lastDI_DT: "+LocalInfo.lastDI_DT);
            }
            else if (softwareType == "1")
            {
                CameraTriggerThread_Modbus.CameraTrigger_Thread();
                CameraTriggerThread_ModbusOnce.CameraTrigger_Thread();
                CameraTriggerThread_Template.CameraTrigger_Thread();
                CameraTriggerThread_ModbusRealTime.CameraTrigger_Thread();
                TestSetInfoThread.TestSetInfo_Thread();
                //NG_Control.NG_Flow_Thread();                                    
                runStateTimer.Start();
                InitializePLC();
            }

            if (LocalInfo.isStartRun == "1")
            {
                StartIOThread();
            }

        }



        private void Camera_Btn_Click(object sender, EventArgs e)
        {
            CameraReceiveThread.CloseDevice();
            Console.WriteLine("CameraReceiveThread.isGrabbing: "+CameraReceiveThread.isGrabbing);
            if (camera_Form == null)
            {
                camera_Form = new Camera_Form();
                camera_Form.Show();
            }
            else
            {
                camera_Form.TopMost = true;
            }

        }

        private void Template_Btn_Click(object sender, EventArgs e)
        {
            Console.WriteLine("CameraReceiveThread.isGrabbing: " + CameraReceiveThread.isGrabbing);

            //if (template_Form == null)
            //{
            //    template_Form = new Template_Form();
            //    template_Form.ShowDialog();
            //}
            //else
            //{
            //    template_Form.TopMost = true;
            //}


            if (isConfigList)
            {
                if (ProductTemplateConfig_Form == null)
                {
                    ProductTemplateConfig_Form = new ProductTemplateConfig_Form();
                    ProductTemplateConfig_Form.ShowDialog();
                }
                else
                {
                    ProductTemplateConfig_Form.TopMost = true;
                }
            }
            else
            {
                if (multipleRectTemplate_Form == null)
                {
                    multipleRectTemplate_Form = new MultipleRectTemplate_Form();
                    multipleRectTemplate_Form.ShowDialog();
                }
                else
                {
                    multipleRectTemplate_Form.TopMost = true;
                }
            }


        }

        private void Param_Btn_Click(object sender, EventArgs e)
        {
            if (param_Form == null)
            {
                param_Form = new Param_Form();
                param_Form.Show();

                DMC300_Info.NGDelay = ushort.Parse(param_Form.NGDelayTb.Text);              //一开始就将延迟NG吹气时间设定进去
                DMC300_Info.NG_Action = ushort.Parse(param_Form.NG_ActionTb.Text);            //一开始就将NG吹气动作时间设定进去
                DMC300_Info.CameraTrigger_Delay = ushort.Parse(param_Form.CameraTrigger_DelayTb.Text);  //一开始就将相机外部触发延迟时间设定进去
                DMC300_Info.CameraTrigger_Time = ushort.Parse(param_Form.CameraTrigger_TimeTb.Text);   //一开始就将相机外部触发动作时间设定进去
                //LTDMC.dmc_set_el_mode(DMC300_Info.usCardId[0], 0, 0, 0, 0);    //设置轴1的EL限位信号，关闭
                //LTDMC.dmc_set_el_mode(DMC300_Info.usCardId[0], 1, 0, 0, 0);    //设置軸2的EL限位信号，关闭
            }
            else
            {
                param_Form.TopMost = true;
            }


        }

        #region 控件大小随窗体大小等比例缩放
        private readonly float x; //定义当前窗体的宽度
        private readonly float y; //定义当前窗体的高度

        private void setTag(Control cons)
        {
            foreach (Control con in cons.Controls)
            {
                con.Tag = con.Width + ";" + con.Height + ";" + con.Left + ";" + con.Top + ";" + con.Font.Size;
                if (con.Controls.Count > 0) setTag(con);
            }
        }

        private void setControls(float newx, float newy, Control cons)
        {
            //遍历窗体中的控件，重新设置控件的值
            foreach (Control con in cons.Controls)
                //获取控件的Tag属性值，并分割后存储字符串数组
                if (con.Tag != null)
                {
                    var mytag = con.Tag.ToString().Split(';');
                    //根据窗体缩放的比例确定控件的值
                    con.Width = Convert.ToInt32(Convert.ToSingle(mytag[0]) * newx); //宽度
                    con.Height = Convert.ToInt32(Convert.ToSingle(mytag[1]) * newy); //高度
                    con.Left = Convert.ToInt32(Convert.ToSingle(mytag[2]) * newx); //左边距
                    con.Top = Convert.ToInt32(Convert.ToSingle(mytag[3]) * newy); //顶边距
                    var currentSize = Convert.ToSingle(mytag[4]) * newy; //字体大小                   
                    if (currentSize > 0) con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
                    con.Focus();
                    if (con.Controls.Count > 0) setControls(newx, newy, con);
                }
        }
        /// <summary>
        /// 重置窗体布局
        /// </summary>
        private void ReWinformLayout()
        {
            var newx = Width / x;
            var newy = Height / y;
            setControls(newx, newy, this);

        }

        #endregion

        private void OCR_Form_Resize(object sender, EventArgs e)
        {
            //重置窗体大小
            //ReWinformLayout();
        }

        private void OCR_Form_FormClosing(object sender, FormClosingEventArgs e)
        {

            if (softwareType == "0")
            {
                //相机释放资源
                CameraReceiveThread.CloseDevice();

                CameraReceiveThread.StopGrabTrigger();
                CameraTriggerThread.iCameraTrigger_Step = 1;
                CameraTriggerTime_Config.CamearTriggerPause = true;

                LocalInfo.ProductCount_Config_InfoUpdate();

                IOThread_Run.DIORun = false;
                PCI1616_Initial.PCI1616_Close();
            }
            else if (softwareType == "1")
            {
                if (isModbusRealTimeStart)
                {
                    modbusModule.SendData(ModbusModule.bytes_StopRealTime);
                    isModbusRealTimeStart = false;
                }
                //相机释放资源
                CameraReceiveThread.CloseDevice();
                CameraTriggerThread_Modbus.iCameraTrigger_Step = 1;
                //CameraTriggerThread_Modbus.CameraTriggerFlow_Thread.Join();

                //modbusModule.SendData(ModbusModule.MergeArray(ModbusModule.SetWidthByteArray(tbPulseWidth.Text, ModbusModule.bytes_StopState_NoWidth)));
                //modbusModule.SendData(ModbusModule.MergeArray(ModbusModule.bytes_StopState));
                modbusModule.Close();
            }


            //算法销毁实例
            //AlgorithmModule.DestroyInstance();
            //AlgorithmModule_GPU.DestroyInstance();
        }
        private void OCR_Form_FormClosed(object sender, FormClosedEventArgs e)
        {
            //CameraTriggerThread.iCameraTrigger_Step = 1;
            ////算法销毁实例
            //AlgorithmModule.DestroyInstance();
        }

        private void OcrProcess()
        {
            //打开相机  设置相机信息

        }

        private void button1_Click(object sender, EventArgs e)
        {
            //停止
            CameraReceiveThread.StopMotion();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //正向
            CameraReceiveThread.ContinuousMotion();
        }
        private void button3_Click(object sender, EventArgs e)
        {
            //反向
            CameraReceiveThread.BackContinuousMotion();
        }
        private void StartBtn_Click(object sender, EventArgs e)
        {
            StartIOThread();
        }
        public void StartIOThread()
        {
            isMainCameraPbWheel = false;

            LocalInfo.currCount = 0;

            checkBox1.Enabled = false;//软触发

            CloseAllGroupBox();

            StartBtn.Hide();
            StopBtn.Show();

            CreateFolderThread.CreateFolder_Pause = false;
            CreateFolderThread.iCreateFolder_Step = 10;

            if (LocalInfo.CheckDI == "0")
            {
                CameraTriggerThread.iCameraTrigger_Step = 22;
            }
            else if (LocalInfo.CheckDI == "1")
            {
                CameraTriggerThread.iCameraTrigger_Step = 10;
            }
            //CameraTriggerThread.iCameraTrigger_Step = 10;
            CameraTriggerTime_Config.CamearTriggerPause = false;

            if (!CameraReceiveThread.isGrabbing)
            {
                CameraReceiveThread.RefreshDeviceList();
            }

            CameraOnlineThread.CameraOnlineThread_Pause = false;
            CameraOnlineThread.iCameraOnline_Step = 5;

            LightStateDo(7);

            richTB_State_PLC.AppendText("IO线程开启..." + DateTime.Now.ToString("yyyy-MM-dd-HH:mm:ss") + "\r\n");

            Console.WriteLine("LocalInfo.CloseSignalDelayTime..." + LocalInfo.CloseSignalDelayTime);
        }
        private void StopBtn_Click(object sender, EventArgs e)
        {
            //CameraReceiveThread.StopGrabTrigger();
            //相机释放资源
            //CameraReceiveThread.CloseDevice();
            //停止运动
            //CameraReceiveThread.StopMotion();

            //checkBox1.Enabled = true;

            isMainCameraPbWheel = true;

            StopCameraTriggerThread();

        }
        public void StopCameraTriggerThread()
        {
            if (LocalInfo.PermissionIndex == 0)
            {
                checkBox1.Enabled = true;//软触发
                OpenAllGroupBox();
            }
            else
            {

            }

            StartBtn.Show();
            StopBtn.Hide();




            CreateFolderThread.iCreateFolder_Step = 1;
            CreateFolderThread.CreateFolder_Pause = true;

            CameraTriggerThread.iCameraTrigger_Step = 1;
            CameraTriggerTime_Config.CamearTriggerPause = true;

            LocalInfo.ProductCount_Config_InfoUpdate();

            LightStateDo(8);

            richTB_State_PLC.AppendText("IO线程停止..." + DateTime.Now.ToString("yyyy-MM-dd-HH:mm:ss") + "\r\n");
        }

        public static CameraOfflineForm cameraOfflineForm;
        public void ShowCameraOfflineForm()
        {
            if (cameraOfflineForm == null)
            {
                cameraOfflineForm = new CameraOfflineForm();
                cameraOfflineForm.ShowDialog();
            }
            else
            {
                cameraOfflineForm.TopMost = true;
            }
        }

        private void runStateTimer_Tick(object sender, EventArgs e)
        {
            //ushort usAxis = 0;  //轴号
            //double dCurrentVel = 0;     //速度
            //int nCmdPos = 0;         //指令位置
            //int nEnPos = 0;          //编码器反馈位置

            //dCurrentVel = LTDMC.dmc_read_current_speed(DMC300_Info.usCardId[0], usAxis); // 读取轴当前速度
            //currSpeed.Text = dCurrentVel.ToString();
            //nCmdPos = LTDMC.dmc_get_position(DMC300_Info.usCardId[0], usAxis);           //读取指定轴指令位置值
            //currLocationTb.Text = nCmdPos.ToString();
            //nEnPos = LTDMC.dmc_get_encoder(DMC300_Info.usCardId[0], usAxis);             //读取指定轴的编码器反馈值
            //feedBackTb.Text = nEnPos.ToString();

            //if (LTDMC.dmc_check_done(DMC300_Info.usCardId[0], usAxis) == 0)                      //读取指定轴运动状态
            //{
            //    runStateTb.Text = "运行中";
            //}
            //else
            //{
            //    runStateTb.Text = "停止中";
            //}

            isSaveImg = saveOKImgcB.Checked;

            TotalCountTb.Text = LocalInfo.totalCount.ToString();
            NGCountTb.Text = LocalInfo.ngCount.ToString();
        }
        private void StateClearBtn_Click(object sender, EventArgs e)
        {
            ushort usAxis = 0;                           //轴号
            int dPos = 0;                                     // 当前位置
            LTDMC.dmc_set_position(DMC300_Info.usCardId[0], usAxis, dPos); //设置指定轴的当前指令位置值歸零
            LTDMC.dmc_set_encoder(DMC300_Info.usCardId[0], usAxis, dPos);  //設置指定軸編碼器歸零
        }

        private void ChangeSpeedBtn_Click(object sender, EventArgs e)
        {
            ushort usAxis = 0; //轴号
            double dNewVel = Double.Parse(changeSpeedTb.Text);                // 新的运行速度
            double dTaccDec = Double.Parse(changeTimeTb.Text);              //变速时间
            LTDMC.dmc_change_speed(DMC300_Info.usCardId[0], usAxis, dNewVel, dTaccDec);  //在线变速
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                if (!CameraReceiveThread.isGrabbing)
                {
                    checkBox1.Checked = false;
                    return;
                }

                // ch:触发源设为软触发 | en:Set trigger source as Software
                CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerSource", "Software");
                CameraTriggerTime_Config.CamearTriggerPause = true;
                isSaveImg = false;
                //saveImgcB.Checked = false;
                button2.Enabled = false;
                button3.Enabled = false;
                button1.Enabled = false;
                StartBtn.Enabled = false;
                SetgB.Enabled = false;
                if (CameraReceiveThread.isGrabbing)
                {
                    softTriggerOnceBtn.Enabled = true;
                }
            }
            else
            {
                if (!CameraReceiveThread.isGrabbing)
                {
                    MessageBox.Show("相机未连接");
                    return;
                }
                CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerSource", "Line0");
                CameraTriggerTime_Config.CamearTriggerPause = false;
                softTriggerOnceBtn.Enabled = false;
                isSaveImg = true;
                //saveImgcB.Checked = true;
                button2.Enabled = true;
                button3.Enabled = true;
                button1.Enabled = true;
                StartBtn.Enabled = true;
                SetgB.Enabled = true;
            }
        }

        private void softTriggerOnceBtn_Click(object sender, EventArgs e)
        {
            int result = CameraReceiveThread.device.Parameters.SetCommandValue("TriggerSoftware");
            if (result != MvError.MV_OK)
            {
                CameraReceiveThread.ShowErrorMsg("Trigger Software Fail!", result);
            }
            Thread.Sleep(50);
            Console.WriteLine("软触时间" + DateTime.Now.Millisecond);
            Console.WriteLine("软触一次" + CameraReceiveThread.isImageData);

            //AlgorithmModule.ImageHandleV2();
            //mainCameraPb.Image = AlgorithmModule.RectPoints();

            //AlgorithmModule_GPU.ImageHandleV2_Opencv(CameraReceiveThread.frameForSave.Image.ToBitmap());
            AlgorithmModule_GPU.ImageHandleV2_ByteArray(CameraReceiveThread.frameForSave.Image.ToBitmap());

            mainCameraPb.Image = AlgorithmModule_GPU.RectPoints1(CameraReceiveThread.frameForSave.Image.ToBitmap(), AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            mainCameraPb.SizeMode = PictureBoxSizeMode.Zoom;
            mainCameraPb.BackgroundImageLayout = ImageLayout.Zoom;
        }

        private void saveOKImgcB_CheckedChanged(object sender, EventArgs e)
        {
            if (saveOKImgcB.Checked)
            {
                LocalInfo.isSaveOK = "1";

            }
            else
            {
                LocalInfo.isSaveOK = "0";
            }
            LocalInfo.isSaveOK_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.isSaveOK:  " + LocalInfo.isSaveOK);
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            if (saveNGImgcB.Checked )
            {
                CameraTriggerTime_Config.SaveOriginalImageCh = true;
            }
            else
            {
                CameraTriggerTime_Config.SaveOriginalImageCh = false;
            }
        }


        public static string softwareType;
        private void SetSofrwareType()
        {
            string path=Application.StartupPath+"\\Config\\TypeConfig.json";
            SoftwareType_Config softwareType_Config = new SoftwareType_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            softwareType_Config = JsonMapper.ToObject<SoftwareType_Config>(re);
            softwareType= softwareType_Config.Type;



            switch (softwareType_Config.Type)
            {
                case "0":
                    //gbInfos_0.Show();       //识别信息
                    //gbRunState_0.Show();    //运行状态
                    //gbSpeedChange_0.Show();  //速度变换
                    StartBtn.Show();         //运行按钮
                    gbSofrwareState_1.Show();  //软件状态
                    gbResult_1.Show();         //NG结果
                    IO_TestGB.Show();   //IO卡功能测试
                    LocalFileGb.Show();
                    break;
                case "1":
                    gbInfos_1.Show();          //识别信息
                    gbSofrwareState_1.Show();  //软件状态
                    gbResult_1.Show();         //NG结果
                    gbTest_1.Show();           //PLC 运动测试
                    StartBtn_PLC.Show();       //运行按钮
                    //countGB.Show();      //计数

                    break;
                default:
                    break;
            }
        }

        private void SetOutImgPath()
        {
            string path = Application.StartupPath + "\\Config\\OutImgPathConfig.json";
            OutImgPath_Config outImgPath_Config = new OutImgPath_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            outImgPath_Config = JsonMapper.ToObject<OutImgPath_Config>(re);
            LocalInfo.outImgPath = outImgPath_Config.OutPath;
            if (!Directory.Exists(LocalInfo.outImgPath))
            {
                Directory.CreateDirectory(LocalInfo.outImgPath);
            }
            sr.Dispose();
        }

        bool isModbusStart;
        private void StartBtn_PLC_Click(object sender, EventArgs e)
        {
            if (!CameraReceiveThread.isGrabbing)
            {
                CameraReceiveThread.CameraInitialize();
            }
            Console.WriteLine("LocalInfo.imgScale: " + LocalInfo.imgScale);

            SetgB.Enabled = false;
            StartBtn_PLC.Hide();
            StopBtn_PLC.Show();
            gbTest_1.Enabled = false;



            //if (!isModbusRealTimeStart)
            //{
            //    modbusModule.SendData(ModbusModule.bytes_StartRealTime);
            //    isModbusRealTimeStart = true;
            //    Console.WriteLine("是否实时:  " + isModbusRealTimeStart);
            //}
            if (OCR_Form.softwareType == "0")
            {
               CameraReceiveThread.StartGrabTrigger();//启动触发流程
            }
            else if (OCR_Form.softwareType == "1")
            {
                modbusModule.SendData(ModbusModule.MergeArray(ModbusModule.SetWidthByteArray(tbPulseWidth.Text, ModbusModule.bytes_StartState_NoWidth)));

                CameraReceiveThread.StartGrabTrigger_Modbus();
            }

        }
        private void InitializePLC()
        {
            modbusModule.Open();
            //modbusModule.SendData(ModbusModule.MergeArray(ModbusModule.SetWidthByteArray(tbPulseWidth.Text, ModbusModule.bytes_StartState_NoWidth)));
            //modbusModule.SendData(ModbusModule.MergeArray(ModbusModule.bytes_StartState));

            isModbusStart = true;
            //开启触发线程

            //Console.WriteLine("是否实时:  " + isModbusRealTimeStart);
        }

        private void StopBtn_PLC_Click(object sender, EventArgs e)
        {
            SetgB.Enabled = true;
            StartBtn_PLC.Show();
            StopBtn_PLC.Hide();
            gbTest_1.Enabled = true;

            //相机释放资源
            //CameraReceiveThread.CloseDevice();

            //if (isModbusRealTimeStart)
            //{
            //    modbusModule.SendData(ModbusModule.bytes_StopRealTime);
            //    isModbusRealTimeStart = false;
            //}

            CameraReceiveThread.StopGrabTrigger_Modbus();

            modbusModule.SendData(ModbusModule.MergeArray(ModbusModule.SetWidthByteArray(tbPulseWidth.Text, ModbusModule.bytes_StopState_NoWidth)));
            //modbusModule.Close();

            //OCR_Form.oCR_Form.richTB_State_PLC.AppendText("\r\n停止运行..." + DateTime.Now.ToString("yyyy-MM-dd-HH:mm:ss"));
        }

        public static bool isModbusRealTimeStart;
        private void StartRealTimeBtn_Click(object sender, EventArgs e)
        {
            StartBtn_PLC.Enabled = false;
            StartRealTimeBtn.Enabled = false;
            StopRealTimeBtn.Enabled = true;

            //if (!isModbusRealTimeStart)
            //{
            //    modbusModule.SendData(ModbusModule.bytes_StartRealTime);
            //    isModbusRealTimeStart = true;
            //    Console.WriteLine("是否实时:  " + isModbusRealTimeStart);
            //}

            modbusModule.SendData(ModbusModule.bytes_StartRealTime);
            isModbusRealTimeStart = true;
            Console.WriteLine("是否实时:  " + isModbusRealTimeStart);

            CameraTriggerThread_ModbusRealTime.iCameraTrigger_Step = 5;
        }

        private void StopRealTimeBtn_Click(object sender, EventArgs e)
        {
            StartBtn_PLC.Enabled = true;
            StartRealTimeBtn.Enabled = true;
            StopRealTimeBtn.Enabled = false;

            modbusModule.SendData(ModbusModule.bytes_StopRealTime);
            isModbusRealTimeStart = false;
            Console.WriteLine("是否实时:  " + isModbusRealTimeStart);
            CameraTriggerThread_ModbusRealTime.iCameraTrigger_Step = 0;
        }
        public static DateTime grabImgTime;
        private void SingleTriggerBtn_Click(object sender, EventArgs e)
        {
            if (!CameraReceiveThread.isGrabbing)
            {
                CameraReceiveThread.CameraInitialize();
            }
            Console.WriteLine("LocalInfo.imgScale: " + LocalInfo.imgScale);
            modbusModule.SendData(ModbusModule.bytes_SingleTrigger);
            CameraTriggerThread_ModbusOnce.iCameraTrigger_Step = 5;
            grabImgTime = DateTime.Now;
            Console.WriteLine("开始获取图片信息");
            //AlgorithmModule.ImageHandleV2_OnceTri_Modbus();
        }
        public static void ModbusSingleTrigger()
        {
            Console.WriteLine("Template_Form.isRect: " + Template_Form.isRect);
            if (!CameraReceiveThread.isGrabbing)
                return;
            Console.WriteLine("模板窗口开始获取图片信息");

            modbusModule.SendData(ModbusModule.bytes_SingleTrigger);
            CameraTriggerThread_Template.iCameraTrigger_Step = 5;
            grabImgTime = DateTime.Now;

        }
        private void ModbusNgBtn_Click(object sender, EventArgs e)
        {
            modbusModule.SendData(ModbusModule.bytes_NG);
        }

        public static void ModbusSendNg()
        {
           modbusModule.SendData(ModbusModule.bytes_NG);
        }

        public bool isSaveImg_NG;

        private void saveImgCb_PLC_CheckedChanged(object sender, EventArgs e)
        {
            //不勾选 只保存NG
            //勾选  NG/OK都保存
            if (saveImgCb_PLC.Checked)
            {
                isSaveImg_NG = false;
            }
            else
            {
                isSaveImg_NG = true;
            }
        }

        private void saveOriginImgCb_PLC_CheckedChanged(object sender, EventArgs e)
        {
            //勾选保存原图
            if (saveOriginImgCb_PLC.Checked)
            {
                CameraTriggerTime_Config.SaveOriginalImageCh = true;
            }
            else
            {
                CameraTriggerTime_Config.SaveOriginalImageCh = false;
            }
        }


        int GB = 1024 * 1024 * 1024;//定义GB的计算常量
        int MB = 1024 * 1024;//定义MB的计算常量
        int KB = 1024;//定义KB的计算常量
        /// <summary>
        /// 超过当前磁盘容量85%  清理图片文件夹  
        /// </summary>
        /// <param name="remainCount">剩余文件夹个数</param>
        public void ClearOutImg(int remainCount)
        {
            string outImgPath = Application.StartupPath + "\\out\\";
            string rootPath = Application.StartupPath.Split(':')[0];
            //Console.WriteLine(rootPath);
            long temp_Total = GetHardDiskSpace(rootPath);
            long temp_Remaining = GetHardDiskFreeSpace(rootPath);
            float temp_Total_GB = temp_Total / GB;
            float temp_Remaining_GB = temp_Remaining / GB;
            //Console.WriteLine(temp_Total_GB);
            //Console.WriteLine(temp_Remaining_GB);
            //Console.WriteLine(temp_Remaining_GB / temp_Total_GB);
            if (temp_Remaining_GB / temp_Total_GB <= 0.15f)
            {
                //Console.WriteLine("超出容量，清理图片文件夹");
                DirectoryInfo outDirInfo = new DirectoryInfo(outImgPath);
                DirectoryInfo[] outFileInfo = outDirInfo.GetDirectories();
                List<string> outFilesList = new List<string>();

                if (outFileInfo.Length < remainCount)
                    return;

                foreach (DirectoryInfo item in outFileInfo)
                {
                    //Console.WriteLine("输出图片文件夹：" + item.Name);
                    outFilesList.Add(item.Name);
                }

                List<int> removeIndexList = new List<int>();
                for (int i = 0; i < outFilesList.Count; i++)
                {
                    if (i < outFilesList.Count - remainCount)
                    {
                        removeIndexList.Add(i);
                    }
                }

                foreach (var item in removeIndexList)
                {
                    //Console.WriteLine("删除的文件夹：" + outFileInfo[item].ToString());
                    if (Directory.Exists(outImgPath + outFileInfo[item]))
                    {
                        Directory.Delete(outImgPath + outFileInfo[item],true);
                    }

                }
            }
            else
            {
                //Console.WriteLine("Diskstatus:{0}","OutOfRange");
            }
        }

        /// 获取指定驱动器的空间总大小(单位为B) 
        /// </summary> 
        /// <param name="str_HardDiskName">只需输入代表驱动器的字母即可 </param> 
        /// <returns> </returns> 
        public static long GetHardDiskSpace(string str_HardDiskName)
        {
            long totalSize = new long();
            str_HardDiskName = str_HardDiskName + ":\\";
            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            foreach (System.IO.DriveInfo drive in drives)
            {
                if (drive.Name == str_HardDiskName)
                {
                    totalSize = drive.TotalSize;
                }
            }
            return totalSize;
        }

        /// <summary> 
        /// 获取指定驱动器的剩余空间总大小(单位为B) 
        /// </summary> 
        /// <param name="str_HardDiskName">只需输入代表驱动器的字母即可 </param> 
        /// <returns> </returns> 
        public static long GetHardDiskFreeSpace(string str_HardDiskName)
        {
            long freeSpace = new long();
            str_HardDiskName = str_HardDiskName + ":\\";
            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            foreach (System.IO.DriveInfo drive in drives)
            {
                if (drive.Name == str_HardDiskName)
                {
                    freeSpace = drive.TotalFreeSpace;
                }
            }
            return freeSpace;
        }

        public AlgorithmForm algorithmForm;
        private void AlgorithmBtn_Click(object sender, EventArgs e)
        {
            if (algorithmForm == null)
            {
                algorithmForm = new AlgorithmForm();
                algorithmForm.ShowDialog();
            }
            else
            {
                algorithmForm.TopMost = true;
            }
        }

        private void PCI_IO_Btn_Click(object sender, EventArgs e)
        {
            if (pCI1616IO_Form == null)
            {
                pCI1616IO_Form = new PCI1616IO_Form();
                pCI1616IO_Form.ShowDialog();
            }
            else
            {
                pCI1616IO_Form.TopMost = true;
            }
        }

        private void TestSaveImgBtn_Click(object sender, EventArgs e)
        {
            //TestSaveImg();
            if (softwareType == "0")
            {
                //TestRefreshThread.TestSetInfoThread_Pause = false;
                TestSetInfoThread.TestSetInfoThread_Pause = false;
                TestSetInfoThread.iTestSetInfo_Step = 10;

                CreateFolderThread.CreateFolder_Pause = false;
                CreateFolderThread.iCreateFolder_Step = 10;

            }
            else if(softwareType == "1")
            {
                TestSetInfoThread.iTestSetInfo_Step = 0;
            }

        }
        private void StopTestSaveImgBtn_Click(object sender, EventArgs e)
        {
            //TestRefreshThread.TestSetInfoThread_Pause = true;
            TestSetInfoThread.iTestSetInfo_Step = 1;
            TestSetInfoThread.TestSetInfoThread_Pause = true;

            CreateFolderThread.iCreateFolder_Step = 1;
            CreateFolderThread.CreateFolder_Pause = true;

        }
        public static void TestSaveImg()
        {
            Bitmap saveBitmap = (Bitmap)Image.FromFile(LocalTemplateInfo.path);

            DateTime dt1 = DateTime.Now;

            Rectangle cropRect = new Rectangle
(int.Parse(LocalTemplateInfo.rect_X) * 2,
int.Parse(LocalTemplateInfo.rect_Y) * 2,
(int.Parse(LocalTemplateInfo.rect_Right) - int.Parse(LocalTemplateInfo.rect_X)) * 2,
(int.Parse(LocalTemplateInfo.rect_Bottom) - int.Parse(LocalTemplateInfo.rect_Y)) * 2);
            // OCR_Form.oCR_Form.mainCameraPb.Image = AlgorithmModule.CropImage(CameraReceiveThread.frameForSave.Image.ToBitmap(), cropRect, "cropTest.bmp");
            //Image tempImg = AlgorithmModule.CropImageNoRect_opencv(CameraReceiveThread.frameForSave.Image.ToBitmap(), cropRect);
            Image tempImg = AlgorithmModule.CropImageNoRect_opencv_nousing(saveBitmap, cropRect, "", "", LocalInfo.imgScale);
            if (tempImg == null)
            {
                Console.WriteLine("裁剪区域无效");
            }
            DateTime dt2 = DateTime.Now;
            Bitmap final = saveBitmap;
            //Bitmap finalRect= (Bitmap)AlgorithmModule.RectPoints(saveBitmap, AlgorithmModule.convertList); ;


            //oCR_Form.mainCameraPb.Image = AlgorithmModule.RectPoints(saveBitmap, AlgorithmModule.convertList);
            DateTime dt2_Rect = DateTime.Now;

            //            OCR_Form.oCR_Form.InfoTB_01_Modbus.Text = OCR_Form.oCR_Form.InfoTB_02_Modbus.Text = OCR_Form.oCR_Form.InfoTB_03_Modbus.Text = OCR_Form.oCR_Form.InfoTB_04_Modbus.Text
            //= OCR_Form.oCR_Form.InfoTB_05_Modbus.Text = OCR_Form.oCR_Form.InfoTB_06_Modbus.Text = string.Empty;
            if (oCR_Form.InfoTB_01_Modbus.InvokeRequired)
            {
                oCR_Form.InfoTB_01_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_01_Modbus.Text = string.Empty));
            }
            else
            {
                oCR_Form.InfoTB_01_Modbus.Text = string.Empty;
            }

            if (oCR_Form.InfoTB_02_Modbus.InvokeRequired)
            {
                oCR_Form.InfoTB_02_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_02_Modbus.Text = string.Empty));
            }
            else
            {
                oCR_Form.InfoTB_02_Modbus.Text = string.Empty;
            }

            if (oCR_Form.InfoTB_03_Modbus.InvokeRequired)
            {
                oCR_Form.InfoTB_03_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_03_Modbus.Text = string.Empty));
            }
            else
            {
                oCR_Form.InfoTB_03_Modbus.Text = string.Empty;
            }

            if (oCR_Form.InfoTB_04_Modbus.InvokeRequired)
            {
                oCR_Form.InfoTB_04_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_04_Modbus.Text = string.Empty));
            }
            else
            {
                oCR_Form.InfoTB_04_Modbus.Text = string.Empty;
            }

            if (oCR_Form.InfoTB_05_Modbus.InvokeRequired)
            {
                oCR_Form.InfoTB_05_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_05_Modbus.Text = string.Empty));
            }
            else
            {
                oCR_Form.InfoTB_05_Modbus.Text = string.Empty;
            }

            if (oCR_Form.InfoTB_06_Modbus.InvokeRequired)
            {
                oCR_Form.InfoTB_06_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_06_Modbus.Text = string.Empty));
            }
            else
            {
                oCR_Form.InfoTB_06_Modbus.Text = string.Empty;
            }

            if (AlgorithmModule.currConfigs.Count >= 1)
            {
                if (oCR_Form.InfoTB_01_Modbus.InvokeRequired)
                {
                    oCR_Form.InfoTB_01_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_01_Modbus.Text = AlgorithmModule.currConfigs[0].text));
                }
                else
                {
                    oCR_Form.InfoTB_01_Modbus.Text = AlgorithmModule.currConfigs[0].text; ;
                }
            }
            if (AlgorithmModule.currConfigs.Count >= 2)
            {
                if (oCR_Form.InfoTB_02_Modbus.InvokeRequired)
                {
                    oCR_Form.InfoTB_02_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_02_Modbus.Text = AlgorithmModule.currConfigs[1].text));
                }
                else
                {
                    oCR_Form.InfoTB_02_Modbus.Text = AlgorithmModule.currConfigs[1].text; ;
                }
            }
            if (AlgorithmModule.currConfigs.Count >= 3)
            {
                if (oCR_Form.InfoTB_03_Modbus.InvokeRequired)
                {
                    oCR_Form.InfoTB_03_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_03_Modbus.Text = AlgorithmModule.currConfigs[2].text));
                }
                else
                {
                    oCR_Form.InfoTB_03_Modbus.Text = AlgorithmModule.currConfigs[2].text; ;
                }
            }
            if (AlgorithmModule.currConfigs.Count >= 4)
            {
                if (oCR_Form.InfoTB_04_Modbus.InvokeRequired)
                {
                    oCR_Form.InfoTB_04_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_04_Modbus.Text = AlgorithmModule.currConfigs[3].text));
                }
                else
                {
                    oCR_Form.InfoTB_04_Modbus.Text = AlgorithmModule.currConfigs[3].text; ;
                }
            }
            if (AlgorithmModule.currConfigs.Count >= 5)
            {
                if (oCR_Form.InfoTB_05_Modbus.InvokeRequired)
                {
                    oCR_Form.InfoTB_05_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_05_Modbus.Text = AlgorithmModule.currConfigs[4].text));
                }
                else
                {
                    oCR_Form.InfoTB_05_Modbus.Text = AlgorithmModule.currConfigs[4].text; ;
                }
            }
            if (AlgorithmModule.currConfigs.Count >= 6)
            {
                if (oCR_Form.InfoTB_06_Modbus.InvokeRequired)
                {
                    oCR_Form.InfoTB_06_Modbus.BeginInvoke(new Action(() => oCR_Form.InfoTB_06_Modbus.Text = AlgorithmModule.currConfigs[5].text));
                }
                else
                {
                    oCR_Form.InfoTB_06_Modbus.Text = AlgorithmModule.currConfigs[5].text; ;
                }
            }

            DateTime dt2_Rect_Info = DateTime.Now;
            if (!File.Exists("ImageResult.txt"))
            {
                File.WriteAllText("ImageResult.txt", null, Encoding.UTF8);
            }
            DateTime dt2_Rect_Info_ResultFile = DateTime.Now;

            bool isSame = LocalTemplateInfo.CompareTemplate(AlgorithmModule.currConfigs);
            DateTime dt2_Rect_Info_ResultFile_Compare = DateTime.Now;
            //Console.WriteLine(isSame);
            if (!isSame)
            {
                Console.WriteLine("opencv-NG");

                OCR_Form.ModbusSendNg();

                DateTime SendNgDt = DateTime.Now;

                oCR_Form.mainCameraPb.Image = AlgorithmModule.RectPoints(saveBitmap, AlgorithmModule.convertList);
                DateTime Dt_SetMainPb = DateTime.Now;
                oCR_Form.tbNGResult1.Text = "NG";
                DateTime Dt_SetNGResult = DateTime.Now;
                //OCR_Form.oCR_Form.tbNGResult.Text = "NG";

                try
                {
                    StreamWriter sw = File.AppendText("ImageResult.txt");
                    string timeResult_ng = DateTime.Now.ToString("NG_opencv_记录时间：" + "yyyy:MM:dd:HH:mm:ss.fffffff")
                        + "  算法时长：" + (dt2 - dt1).TotalMilliseconds
                        + "  主界面画框时长：" + (dt2_Rect - dt2).TotalMilliseconds
                        + "  主界面设置信息时长：" + (dt2_Rect_Info - dt2_Rect).TotalMilliseconds
                        + "  无日志创建日志时长：" + (dt2_Rect_Info_ResultFile - dt2_Rect_Info).TotalMilliseconds
                        + "  模板比较时长：" + (dt2_Rect_Info_ResultFile_Compare - dt2_Rect_Info_ResultFile).TotalMilliseconds
                        + "  发送NG时长：" + (SendNgDt - dt2_Rect_Info_ResultFile_Compare).TotalMilliseconds
                        + "  总时长：" + (SendNgDt - dt1).TotalMilliseconds;
                    Console.WriteLine(timeResult_ng);
                    sw.WriteLine(timeResult_ng);
                    sw.Close();

                }
                catch (Exception ex)
                {

                    Console.WriteLine(ex.Message);
                }
                DateTime Dt_SetNGImageResult = DateTime.Now;

                //NG存图
                Console.WriteLine("opencv-NG存图");
                DateTime Dt_SetNGSaveImg = DateTime.Now;
                try
                {
                    string outImgPath = Application.StartupPath + "\\out\\";
                    string tempPath = outImgPath + DateTime.Now.ToString("yyyy-MM-dd") + "\\";
                    //Console.WriteLine(Directory.Exists(tempPath));
                    if (!Directory.Exists(tempPath))
                    {
                        Directory.CreateDirectory(tempPath);
                    }
                    //Console.WriteLine(tempPath);
                    final.Save(tempPath + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "_NG" + ".bmp");
                    DateTime Dt_SetNGSaveOriginImg = DateTime.Now;
                    AlgorithmModule.RectPoints(final, AlgorithmModule.convertList).Save(tempPath + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "_NG_A" + ".bmp");
                    DateTime Dt_SetNGSaveRectImg = DateTime.Now;
                    //CameraReceiveThread.frameForSave.Image.ToBitmap().Save(@"out\\" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "_NG" + ".bmp");
                    //AlgorithmModule.RectPoints(CameraReceiveThread.frameForSave.Image.ToBitmap()).Save(@"out\\" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "_NG_A" + ".bmp");
                    string timeSaveimg_ng = "  存原图时长：" + (Dt_SetNGImageResult - Dt_SetNGResult).TotalMilliseconds
+ "  存画框图时长：" + (Dt_SetNGSaveRectImg - Dt_SetNGSaveOriginImg).TotalMilliseconds;
                    Console.WriteLine(timeSaveimg_ng);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                DateTime Dt_SetNGSaveImgEnd = DateTime.Now;

                string timeENDResult_ng = "  设置主窗口画面时长：" + (Dt_SetMainPb - SendNgDt).TotalMilliseconds
    + "  设置主窗口结果时长：" + (Dt_SetNGResult - Dt_SetMainPb).TotalMilliseconds
    + "  记录日志时长：" + (Dt_SetNGImageResult - Dt_SetNGResult).TotalMilliseconds
    + "  存图时长：" + (Dt_SetNGSaveImgEnd - Dt_SetNGSaveImg).TotalMilliseconds;
                Console.WriteLine(timeENDResult_ng);
            }
            else
            {
                DateTime SendOKDt = DateTime.Now;
                try
                {
                    StreamWriter sw = File.AppendText("ImageResult.txt");
                    // sw.WriteLine(DateTime.Now.ToString("Ok_opencv_记录时间：" + "yyyy:MM:dd:HH:mm:ss.fffffff") + "  " + "进图：" + dt1.TimeOfDay + "  " + "发送OK：" + SendOKDt.TimeOfDay + "  " + "间隔：" + (SendOKDt - dt1).TotalMilliseconds);//yyyy:MM:dd:HH:mm:ss.fffff
                    string timeResult_ok = DateTime.Now.ToString("Ok_opencv_记录时间：" + "yyyy:MM:dd:HH:mm:ss.fffffff")
+ "  算法时长：" + (dt2 - dt1).TotalMilliseconds
+ "  主界面画框时长：" + (dt2_Rect - dt2).TotalMilliseconds
+ "  主界面设置信息时长：" + (dt2_Rect_Info - dt2_Rect).TotalMilliseconds
+ "  无日志创建日志时长：" + (dt2_Rect_Info_ResultFile - dt2_Rect_Info).TotalMilliseconds
+ "  模板比较时长：" + (dt2_Rect_Info_ResultFile_Compare - dt2_Rect_Info_ResultFile).TotalMilliseconds
+ "  发送Ok时长：" + (SendOKDt - dt2_Rect_Info_ResultFile_Compare).TotalMilliseconds
+ "  总时长：" + (SendOKDt - dt1).TotalMilliseconds;
                    Console.WriteLine(timeResult_ok);
                    sw.WriteLine(timeResult_ok);
                    sw.Close();
                }
                catch (Exception ex)
                {

                    Console.WriteLine(ex.Message);
                }
                DateTime Dt_SetOKImageResult = DateTime.Now;

                string outImgPath = Application.StartupPath + "\\out\\";
                string tempPath = outImgPath + DateTime.Now.ToString("yyyy-MM-dd") + "\\";
                //Console.WriteLine(Directory.Exists(tempPath));
                if (!Directory.Exists(tempPath))
                {
                    Directory.CreateDirectory(tempPath);
                }
                Console.WriteLine("opencv-OK");
                //if (oCR_Form.tbNGResult.InvokeRequired)
                //{
                //    oCR_Form.tbNGResult.BeginInvoke(new Action(() => oCR_Form.tbNGResult.Text = "OK"));
                //}
                //else
                //{
                //    oCR_Form.tbNGResult.Text = "OK";
                //}
                OCR_Form.oCR_Form.tbNGResult1.Text = "OK";
                if (OCR_Form.oCR_Form.saveImgCb_PLC.Checked || OCR_Form.oCR_Form.saveOKImgcB.Checked)
                {
                    //OK存图
                    Console.WriteLine("opencv-ok存图");
                    try
                    {
                        final.Save(tempPath + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "_OK" + ".bmp");
                        AlgorithmModule.RectPoints(final, AlgorithmModule.convertList).Save(tempPath + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "_OK_A" + ".bmp");

                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                DateTime Dt_SetOKSaveImgEnd = DateTime.Now;
            }
        }


        public static DateTime dt1;
        public static DateTime dt2;
        public static DateTime dt2_Clone;
        public static DateTime dt_CompareResult;
        public static DateTime SendNgDt;
        public static DateTime SendOKDt;

        public static DateTime triggerDataTime;
        public static DateTime imgDateTime;

        public static Bitmap finalBit;

        /// <summary>
        /// 将多个 ROI 从原图中裁剪出来并横向拼接为一张新图
        /// </summary>
        public static Bitmap StitchROIs(Bitmap src, List<Rectangle> rois, out List<Rectangle> roiLocations, int padding = 2)
        {
            roiLocations = new List<Rectangle>();
            int totalWidth = 0;
            int maxHeight = 0;

            foreach (var roi in rois)
            {
                totalWidth += roi.Width + padding;
                if (roi.Height > maxHeight)
                    maxHeight = roi.Height;
            }


            Bitmap canvas = new Bitmap(totalWidth, maxHeight, PixelFormat.Format24bppRgb);
            using (Graphics g = Graphics.FromImage(canvas))
            {
                g.Clear(Color.Gray);
                int xOffset = 0;
                foreach (var roi in rois)
                {
                    Rectangle target = new Rectangle(xOffset, 0, roi.Width, roi.Height);
                    g.DrawImage(src, target, roi, GraphicsUnit.Pixel);
                    roiLocations.Add(target);
                    xOffset += roi.Width + padding;
                }
            }
            return canvas;
        }

        /// <summary>
        /// 将多个ROI横向拼接并垂直居中
        /// </summary>
        public static Bitmap StitchROIs_Middle(Bitmap src, List<Rectangle> rois, out List<Rectangle> roiLocations, int padding = 2)
        {
            roiLocations = new List<Rectangle>();
            int totalWidth = 0;
            int maxHeight = 0;

            // 计算总宽度和最大高度
            foreach (var roi in rois)
            {
                totalWidth += roi.Width + padding;
                maxHeight = Math.Max(maxHeight, roi.Height);
            }

            //测试出宽度会影响传给算法的图片数据 所有固定设置宽度为500
            if (totalWidth < 500)
            {
                totalWidth = 500;
            }

            Bitmap canvas = new Bitmap(totalWidth, maxHeight, PixelFormat.Format24bppRgb);
            using (Graphics g = Graphics.FromImage(canvas))
            {
                g.Clear(Color.Gray);
                int xOffset = 0;

                foreach (var roi in rois)
                {
                    // 计算垂直居中位置
                    int yOffset = (maxHeight - roi.Height) / 2;
                    Rectangle target = new Rectangle(xOffset, yOffset, roi.Width, roi.Height);

                    g.DrawImage(src, target, roi, GraphicsUnit.Pixel);
                    roiLocations.Add(target);
                    xOffset += roi.Width + padding;
                }
            }
            return canvas;
        }

        /// <summary>
        /// 将拼接图的检测框映射回原图坐标
        /// dets-算法后的框  roiLocations--映射框  rois--外框
        /// </summary>
        public static List<Rectangle> MapBackToOriginal(List<Rectangle> dets, List<Rectangle> roiLocations, List<Rectangle> rois)
        {
            List<Rectangle> mapped = new List<Rectangle>();

            for (int i = 0; i < dets.Count; i++)
            {
                var det = dets[i];

                // 找出属于哪个 ROI
                for (int j = 0; j < roiLocations.Count; j++)
                {
                    if (roiLocations[j].Contains(det.Location))
                    {
                        int dx = det.X - roiLocations[j].X;
                        int dy = det.Y - roiLocations[j].Y;

                        Rectangle mappedBox = new Rectangle(
                            rois[j].X + dx,
                            rois[j].Y + dy,
                            det.Width,
                            det.Height
                        );

                        mapped.Add(mappedBox);
                        break;
                    }
                }
            }
            return mapped;
        }

        // 拼接 ROIs 为一张图
        public static Mat StitchROIs(Mat src, List<Rect> rois, out List<Rect> roiLocations, int padding = 2)
        {
            roiLocations = new List<Rect>();

            int totalWidth = 0;
            int maxHeight = 0;
            foreach (var roi in rois)
            {
                totalWidth += roi.Width;
                maxHeight = Math.Max(maxHeight, roi.Height);
            }

            if (totalWidth < 500)
            {
                totalWidth = 500;
            }

            Mat canvas = new Mat(new OpenCvSharp.Size(totalWidth, maxHeight), src.Type(), Scalar.All(114));
            Console.WriteLine("canvas.Size---" + canvas.Size()+"---" + "canvas.Total()* canvas.ElemSize()==" + canvas.Total()* canvas.ElemSize());
            int xOffset = 0;

            foreach (var roi in rois)
            {
                var roiImg = new Mat(src, roi);
                roiImg.CopyTo(canvas[new Rect(xOffset, 0, roi.Width, roi.Height)]);
                roiLocations.Add(new Rect(xOffset, 0, roi.Width, roi.Height));
                xOffset += roi.Width;
            }
            Console.WriteLine("2222222222222canvas.Size---" + canvas.Size() + "---" + "canvas.Total()* canvas.ElemSize()==" + canvas.Total() * canvas.ElemSize());

            return canvas;
        }


        public static void TestSaveImg_IO1()
        {
            finalBit = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            Console.WriteLine("LocalInfo.Tem_ImgPath:" + LocalInfo.Tem_ImgPath);
            dt1 = DateTime.Now;


            string currTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fffffff");


            for (int i = 0; i < LocalTemplateSingleInfos_Config.rectangles.Count; i++)
            {
                //Console.WriteLine("LocalTemplateSingleInfos_Config.rectangles:"+ LocalTemplateSingleInfos_Config.rectangles[i]);
                
            }

            //List<Rect> opencvRects = new List<Rect>();
            //foreach (var rect in LocalTemplateSingleInfos_Config.rectangles)
            //{
            //    opencvRects.Add(new Rect(rect.X, rect.Y, rect.Width, rect.Height));
            //}
            //List<Rect> roiLocations = new List<Rect>();
            //Mat finalMat = new Mat(LocalInfo.Tem_ImgPath);
            //finalMat = StitchROIs(finalMat, opencvRects, out roiLocations);
            //Console.WriteLine("33333333canvas.Size---" + finalMat.Size() + "---" + "canvas.Total()* canvas.ElemSize()==" + finalMat.Total() * finalMat.ElemSize());
            //finalMat.SaveImage(currTime + "_NG_A_" + Guid.NewGuid().ToString("N") + "_combine_opencv" + ".jpeg");
            //finalBit = (Bitmap)Image.FromStream(finalMat.ToMemoryStream());

            List<Rectangle> roiLocations = new List<Rectangle>();
            finalBit = StitchROIs_Middle(finalBit, LocalTemplateSingleInfos_Config.rectangles, out roiLocations);
            Console.WriteLine("finalBit.Size:-----" + finalBit.Size);
            //finalBit.Save(currTime + "_NG_A_" + Guid.NewGuid().ToString("N") + "_combine" + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);


            AlgorithmModule_GPU.ImageHandleV2_ByteArray(finalBit);

            List<Rectangle> convertRectangles = MapBackToOriginal(ConvertToRectangles(AlgorithmModule_GPU.pointsList), roiLocations,LocalTemplateSingleInfos_Config.rectangles);
            AlgorithmModule_GPU.pointsList = ConvertToPointLists(convertRectangles);

            //LocalInfo.totalCount += 1; 
            LocalInfo.totalCount += LocalInfo.Tem_RectMaxCount;
            dt2 = DateTime.Now;

            dt2_Clone = DateTime.Now;

            //bool isSame = LocalTemplateInfo.CompareTemplate(AlgorithmModule_GPU.mainInfos);

            LocalTemplateSingleInfos_Config.finalPointsList.Clear();
            LocalTemplateSingleInfos_Config.mainInfos.Clear();
            LocalTemplateSingleInfos_Config.temInfos.Clear();

            //储存多个模板所有信息 --temInfos
            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                for (int j = 0; j < LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    LocalTemplateSingleInfos_Config.temInfos.Add(LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList[j]);
                    //Console.WriteLine("temInfos.Count:" + LocalTemplateSingleInfos_Config.temInfos.Count);
                }

            }

            List<bool> isSameList = new List<bool>();
            //传入外框-rectangles，设置多个模板的信息-infosList，是否框内-insideList，点位-finalPointsLists
            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                //LocalTemplateSingleInfos_Config.Compare(LocalTemplateSingleInfos_Config.rectangles[i], LocalTemplateSingleInfos_Config.infosList[i], LocalTemplateSingleInfos_Config.insideList[i], LocalTemplateSingleInfos_Config.finalPointsLists[i]);
                LocalTemplateSingleInfos_Config.CompareConfuse(LocalTemplateSingleInfos_Config.rectangles[i], LocalTemplateSingleInfos_Config.infosList[i], LocalTemplateSingleInfos_Config.insideList[i], LocalTemplateSingleInfos_Config.finalPointsLists[i], LocalTemplateSingleInfos_Config.confuseMultiIndex[i], LocalTemplateSingleInfos_Config.confuseMultiIndexDic[i]);

            }
            //无序对比单个模板内的信息
            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                isSameList.Add(LocalTemplateSingleInfos_Config.CompareTemplate_Disorder(LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList, LocalTemplateSingleInfos_Config.infosList[i]));
            }
            Console.WriteLine("isSameList:" + isSameList.All(x => x));
            bool isSame = isSameList.All(x => x);

            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                //LocalTemplateSingleInfos_Config.CompareTemplate_Disorder_SingleRectInfo(LocalTemplateSingleInfos_Config.infosList[i],LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList);
            }

            //LocalTemplateSingleInfos_Config.CompareTemplate_Disorder_AllInfo(LocalTemplateSingleInfos_Config.temInfos, LocalTemplateSingleInfos_Config.mainInfos);

            //bool isSame = LocalTemplateInfo.CompareTemplate_Disorder(AlgorithmModule_GPU.mainInfos);

            if (LocalInfo.ngOrOkSignal == "0")
            {
                for (int i = 0; i < isSameList.Count; i++)
                {
                    if (!isSameList[i])
                    {
                        //IOThread_Run.DO_Trigger_olng((ushort)(i + 1), 1);
                        switch (i + 1)
                        {
                            case 1:
                                //SendIO_NGThread.iSendIO_NG_Step = 5;
                                break;
                            case 2:
                                //SendIO_NGThread02.iSendIO_NG_Step = 5;
                                break;
                            case 3:
                                //SendIO_NGThread03.iSendIO_NG_Step = 5;
                                break;
                            case 4:
                                //SendIO_NGThread04.iSendIO_NG_Step = 5;
                                break;
                        }
                        Console.WriteLine("ng-------------DO-" + (i + 1).ToString());
                    }
                }
            }
            else if (LocalInfo.ngOrOkSignal == "1")
            {
                for (int i = 0; i < isSameList.Count; i++)
                {
                    if (isSameList[i])
                    {
                        //IOThread_Run.DO_Trigger_olng((ushort)(i + 1), 1);
                        switch (i + 1)
                        {
                            case 1:
                                //SendIO_NGThread.iSendIO_NG_Step = 5;
                                break;
                            case 2:
                                //SendIO_NGThread02.iSendIO_NG_Step = 5;
                                break;
                            case 3:
                                //SendIO_NGThread03.iSendIO_NG_Step = 5;
                                break;
                            case 4:
                                //SendIO_NGThread04.iSendIO_NG_Step = 5;
                                break;
                        }
                        Console.WriteLine("ok-------------DO-" + (i + 1).ToString());
                    }
                }
            }


            dt_CompareResult = DateTime.Now;
            //Console.WriteLine(isSame);
            if (!isSame)
            {
                Console.WriteLine("GPU-NG");

                SendNgDt = DateTime.Now;
                //Console.WriteLine("isSameList--:" + isSameList.ToArray().Count(b => b == false));

                //Console.WriteLine("isSameList--:" + Array.FindAll(isSameList.ToArray(), b => !b).Length);

                int tempNG_Count = isSameList.ToArray().Count(b => b == false);
                LocalInfo.ngCount += tempNG_Count;

                FinalInfoData finalInfoData = new FinalInfoData();
                //finalInfoData.Bitmap = (Bitmap)finalBit.Clone();
                finalInfoData.Bitmap = new Bitmap(Image.FromFile(LocalInfo.Tem_ImgPath));
                finalInfoData.result = "NG";
                finalInfoData.wrongIndex = LocalInfo.wrongIndex;
                finalInfoData.wrongString = LocalInfo.wrongString;
                finalInfoData.isSame = isSameList;
                infoQueue.Enqueue(finalInfoData);

                TestNGControlThread.infoQueue.Enqueue(finalInfoData);

                DelayNgSingleThread.infoQueue.Enqueue(isSame);
            }
            else
            {
                Console.WriteLine("GPU-OK");

                SendOKDt = DateTime.Now;

                FinalInfoData finalInfoData = new FinalInfoData();
                //finalInfoData.Bitmap= (Bitmap)CameraReceiveThread.frameForSave.Image.ToBitmap().Clone();
                finalInfoData.Bitmap = new Bitmap(Image.FromFile(LocalInfo.Tem_ImgPath));
                finalInfoData.result = "OK";
                finalInfoData.wrongIndex = LocalInfo.wrongIndex;
                finalInfoData.wrongString = LocalInfo.wrongString;
                finalInfoData.isSame = isSameList;
                infoQueue.Enqueue(finalInfoData);

                TestNGControlThread.infoQueue.Enqueue(finalInfoData);
                
                DelayNgSingleThread.infoQueue.Enqueue(isSame);
            }
        }
        public static void TestSaveImg_IO2()
        {
            finalBit = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            Console.WriteLine("LocalInfo.Tem_ImgPath:"+LocalInfo.Tem_ImgPath);
            dt1 = DateTime.Now;

            //裁剪拼接
            List<Rectangle> roiLocations = new List<Rectangle>();
            finalBit = StitchROIs_Middle(finalBit, LocalTemplateSingleInfos_Config.rectangles, out roiLocations);

            //string currTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fffffff");
            //finalBit.Save(Application.StartupPath + "\\test\\" + currTime + "_NG_A_" + Guid.NewGuid().ToString("N") + "_combine" + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);


            //AlgorithmModule_GPU.ImageHandleV2_ByteArray(finalBit);
            AlgorithmModule_GPU.ImageHandleV2_Opencv(finalBit);

            //映射回原图
            List<Rectangle> convertRectangles = MapBackToOriginal(ConvertToRectangles(AlgorithmModule_GPU.pointsList), roiLocations, LocalTemplateSingleInfos_Config.rectangles);
            AlgorithmModule_GPU.pointsList = ConvertToPointLists(convertRectangles);

            //AlgorithmModule_GPU.ImageHandleV2_ByteArray(finalBit);

            //LocalInfo.totalCount += 1; 
            LocalInfo.totalCount += LocalInfo.Tem_RectMaxCount;
            dt2 = DateTime.Now;

            dt2_Clone = DateTime.Now;

            //bool isSame = LocalTemplateInfo.CompareTemplate(AlgorithmModule_GPU.mainInfos);

            LocalTemplateSingleInfos_Config.finalPointsList.Clear();
            LocalTemplateSingleInfos_Config.mainInfos.Clear();
            LocalTemplateSingleInfos_Config.temInfos.Clear();

            //储存多个模板所有信息 --temInfos
            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                for (int j = 0; j < LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    LocalTemplateSingleInfos_Config.temInfos.Add(LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList[j]);
                    //Console.WriteLine("temInfos.Count:" + LocalTemplateSingleInfos_Config.temInfos.Count);
                }

            }

            List<bool> isSameList = new List<bool>();
            //传入外框-rectangles，设置多个模板的信息-infosList，是否框内-insideList，点位-finalPointsLists
            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                //LocalTemplateSingleInfos_Config.Compare(LocalTemplateSingleInfos_Config.rectangles[i], LocalTemplateSingleInfos_Config.infosList[i], LocalTemplateSingleInfos_Config.insideList[i], LocalTemplateSingleInfos_Config.finalPointsLists[i]);
                LocalTemplateSingleInfos_Config.CompareConfuse(LocalTemplateSingleInfos_Config.rectangles[i], LocalTemplateSingleInfos_Config.infosList[i], LocalTemplateSingleInfos_Config.insideList[i], LocalTemplateSingleInfos_Config.finalPointsLists[i], LocalTemplateSingleInfos_Config.confuseMultiIndex[i], LocalTemplateSingleInfos_Config.confuseMultiIndexDic[i]);

            }
            //无序对比单个模板内的信息
            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                isSameList.Add(LocalTemplateSingleInfos_Config.CompareTemplate_Disorder(LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList, LocalTemplateSingleInfos_Config.infosList[i]));
            }
            Console.WriteLine("isSameList.Count:" + isSameList.Count);
            Console.WriteLine("isSameList:"+ isSameList.All(x => x));
            bool isSame = isSameList.All(x => x);

            for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
            {
                //LocalTemplateSingleInfos_Config.CompareTemplate_Disorder_SingleRectInfo(LocalTemplateSingleInfos_Config.infosList[i],LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList);
            }

            //LocalTemplateSingleInfos_Config.CompareTemplate_Disorder_AllInfo(LocalTemplateSingleInfos_Config.temInfos, LocalTemplateSingleInfos_Config.mainInfos);

            //bool isSame = LocalTemplateInfo.CompareTemplate_Disorder(AlgorithmModule_GPU.mainInfos);

            if (LocalInfo.ngOrOkSignal == "0")
            {
                for (int i = 0; i < isSameList.Count; i++)
                {
                    if (!isSameList[i])
                    {
                        IOThread_Run.DO_Trigger_olng((ushort)(i + 1), 1);
                        Console.WriteLine("ng-------------DO-" + (i + 1).ToString());
                    }
                }
                SendIO_NGThread_All.iSendIO_NG_Step = 5;
            }
            else if (LocalInfo.ngOrOkSignal == "1")
            {

                //if (isSameList[0])
                //{
                //    Console.WriteLine("IOThread_Run.DO_Trigger_olng[0]:" + isSameList[0]);
                //    IOThread_Run.DO_Trigger_olng(1, 1);
                //}
                //if (isSameList[1])
                //{
                //    Console.WriteLine("IOThread_Run.DO_Trigger_olng[1]:" + isSameList[1]);
                //    IOThread_Run.DO_Trigger_olng(2, 1);
                //}
                //if (isSameList[2])
                //{
                //    Console.WriteLine("IOThread_Run.DO_Trigger_olng[2]:" + isSameList[2]);
                //    IOThread_Run.DO_Trigger_olng(3, 1);
                //}
                //if (isSameList[3])
                //{
                //    Console.WriteLine("IOThread_Run.DO_Trigger_olng[3]:" + isSameList[3]);
                //    IOThread_Run.DO_Trigger_olng(4, 1);

                //}

                for (int i = 0; i < isSameList.Count; i++)
                {
                    if (isSameList[i])
                    {
                        IOThread_Run.DO_Trigger_olng((ushort)(i + 1), 1);
                        Console.WriteLine("ok-------------DO-" + (i + 1).ToString());
                    }
                }

                SendIO_NGThread_All.iSendIO_NG_Step = 5;

            }


            dt_CompareResult = DateTime.Now;
            //Console.WriteLine(isSame);
            if (!isSame)
            {
                Console.WriteLine("GPU-NG");

                SendNgDt = DateTime.Now; 
                //Console.WriteLine("isSameList--:" + isSameList.ToArray().Count(b => b == false));

                //Console.WriteLine("isSameList--:" + Array.FindAll(isSameList.ToArray(), b => !b).Length);

                int tempNG_Count = isSameList.ToArray().Count(b => b == false);
                LocalInfo.ngCount += tempNG_Count;

                FinalInfoData finalInfoData = new FinalInfoData();
                //finalInfoData.Bitmap = (Bitmap)finalBit.Clone();
                finalInfoData.Bitmap = new Bitmap(Image.FromFile(LocalInfo.Tem_ImgPath));
                finalInfoData.result = "NG";
                finalInfoData.wrongIndex = LocalInfo.wrongIndex;
                finalInfoData.wrongString = LocalInfo.wrongString;
                finalInfoData.isSame = isSameList;
                infoQueue.Enqueue(finalInfoData);

                TestNGControlThread.infoQueue.Enqueue(finalInfoData);

                DelayNgSingleThread.infoQueue.Enqueue(isSame);
            }
            else
            {
                Console.WriteLine("GPU-OK");

                SendOKDt = DateTime.Now;

                FinalInfoData finalInfoData = new FinalInfoData();
                //finalInfoData.Bitmap= (Bitmap)CameraReceiveThread.frameForSave.Image.ToBitmap().Clone();
                finalInfoData.Bitmap = new Bitmap(Image.FromFile(LocalInfo.Tem_ImgPath));
                finalInfoData.result = "OK";
                finalInfoData.wrongIndex = LocalInfo.wrongIndex;
                finalInfoData.wrongString = LocalInfo.wrongString;
                finalInfoData.isSame = isSameList;
                infoQueue.Enqueue(finalInfoData);

                TestNGControlThread.infoQueue.Enqueue(finalInfoData);

                DelayNgSingleThread.infoQueue.Enqueue(isSame);
            }
        }

        public static ConcurrentQueue<FinalInfoData> infoQueue = new ConcurrentQueue<FinalInfoData>();
        private void StartUpdateUIThreads()
        {
            // 初始化UI更新的定时器（每100毫秒检查一次）
            updateUITimer = new System.Windows.Forms.Timer { Interval = 20 };
            updateUITimer.Tick += UpdateUI;
            updateUITimer.Start(); 
        }
        public  void UpdateUI(object sender, EventArgs e)
        {
            while (infoQueue.TryDequeue(out FinalInfoData info))
            {
                // 安全释放旧图像资源
                if (mainCameraPb.Image != null)
                {
                    var oldImage = mainCameraPb.Image;
                    mainCameraPb.Image = null;
                    oldImage.Dispose();

                }

                //AlgorithmModule.LocalCompare(AlgorithmModule.pointsList);

                DateTime dt_Set_Info = DateTime.Now;
                InfoTB_01.Text = InfoTB_02.Text = InfoTB_03.Text = InfoTB_04.Text = InfoTB_05.Text = InfoTB_06.Text = string.Empty;
                //if (AlgorithmModule_GPU.mainInfos.Count >= 1)
                //    InfoTB_01.Text = AlgorithmModule_GPU.mainInfos[0];
                //if (AlgorithmModule_GPU.mainInfos.Count >= 2)
                //    InfoTB_02.Text = AlgorithmModule_GPU.mainInfos[1];
                //if (AlgorithmModule_GPU.mainInfos.Count >= 3)
                //    InfoTB_03.Text = AlgorithmModule_GPU.mainInfos[2];
                //if (AlgorithmModule_GPU.mainInfos.Count >= 4)
                //    InfoTB_04.Text = AlgorithmModule_GPU.mainInfos[3];
                //if (AlgorithmModule_GPU.mainInfos.Count >= 5)
                //    InfoTB_05.Text = AlgorithmModule_GPU.mainInfos[4];
                //if (AlgorithmModule_GPU.mainInfos.Count >= 6)
                //    InfoTB_06.Text = AlgorithmModule_GPU.mainInfos[5];

                if (LocalTemplateSingleInfos_Config.infosList[0].Count >= 1)
                    InfoTB_01.Text = LocalTemplateSingleInfos_Config.infosList[0][0];
                if (LocalTemplateSingleInfos_Config.infosList[0].Count >= 2)
                    InfoTB_02.Text = LocalTemplateSingleInfos_Config.infosList[0][1];
                if (LocalTemplateSingleInfos_Config.infosList[0].Count >= 3)
                    InfoTB_03.Text = LocalTemplateSingleInfos_Config.infosList[0][2];
                if (LocalTemplateSingleInfos_Config.infosList[0].Count >= 4)
                    InfoTB_04.Text = LocalTemplateSingleInfos_Config.infosList[0][3];
                if (LocalTemplateSingleInfos_Config.infosList[0].Count >= 5)
                    InfoTB_05.Text = LocalTemplateSingleInfos_Config.infosList[0][4];
                if (LocalTemplateSingleInfos_Config.infosList[0].Count >= 6)
                    InfoTB_06.Text = LocalTemplateSingleInfos_Config.infosList[0][5];

                DateTime dt_MainRect = DateTime.Now;
                List<List<System.Drawing.Point>> currPointsList = new List<List<System.Drawing.Point>>();
                for (int i = 0; i < AlgorithmModule_GPU.finalPointList.Count; i++)
                {
                    currPointsList.Add(AlgorithmModule_GPU.finalPointList[i]);
                }
                //currPointsList = AlgorithmModule.pointsList;
                // 更新UI控件
                //mainCameraPb.Image = AlgorithmModule_GPU.RectPoints(info.Bitmap, currPointsList);
                //mainCameraPb.Image = AlgorithmModule_GPU.RectPoints((Bitmap)AlgorithmModule_GPU.RectPoints(info.Bitmap, currPointsList, LocalInfo.wrongIndex),LocalTemplateInfo.rectangle);

                //mainCameraPb.Image = AlgorithmModule_GPU.RectPoints((Bitmap)AlgorithmModule_GPU.RectPoints1(info.Bitmap, currPointsList, info.wrongIndex, AlgorithmModule_GPU.mainInfos),LocalTemplateInfo.rectangle);

                Image tempImg = AlgorithmModule_GPU.RectPoints(
                    (Bitmap)AlgorithmModule_GPU.RectPoints1(info.Bitmap,LocalTemplateSingleInfos_Config.finalPointsList,info.wrongIndex,LocalTemplateSingleInfos_Config.mainInfos,info.wrongString)
                    , LocalTemplateSingleInfos_Config.rectangles,info.isSame);
                mainCameraPb.Image = LocalTemplateSingleInfos_Config.RectDrawString((Bitmap)tempImg, info.isSame);

                ReturnManiCameraPb();

                DateTime dt_MainResult = DateTime.Now;
                tbNGResult.Text = info.result;
                if (tbNGResult.Text == "NG")
                {
                    Console.WriteLine("tbNGResult.Text = NG");
                    //tbNGResult.ForeColor = Color.White;
                    tbNGResult.ForeColor = Color.Red;
                }
                else if (tbNGResult.Text == "OK")
                {
                    tbNGResult.ForeColor = Color.SpringGreen;
                }

                DateTime dt_isImageResult = DateTime.Now;
                //if (!File.Exists("ImageResult.txt"))
                //{
                //    File.WriteAllText("ImageResult.txt", null, Encoding.UTF8);
                //}
                if (!Directory.Exists("ImageResultFiles"))
                {
                    Directory.CreateDirectory("ImageResultFiles");
                }
                ProcessFile("ImageResult.txt");
                DateTime dt_Txt = DateTime.Now;
                string currTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fffffff");

                if (LocalInfo.isLog == "0")
                {

                    try
                    {
                        StreamWriter sw = File.AppendText("ImageResult.txt");
                        string temp = info.result;
                        if (temp == "OK")
                            temp = "Ok";


                        string timeResult_ng = temp + "_GPU_记录时间：" + currTime
                            + "  算法耗时：" + AlgorithmModule_GPU.dt1_dt2_time
                            + "  算法时长：" + (CameraTriggerThread.dt2 - CameraTriggerThread.dt1).TotalMilliseconds
                            + "  克隆相机图片时长：" + (CameraTriggerThread.dt2_Clone - CameraTriggerThread.dt2).TotalMilliseconds
                            + "  模板比较时长：" + (CameraTriggerThread.dt_CompareResult - CameraTriggerThread.dt2_Clone).TotalMilliseconds
                            + "  算法-克隆-比较时长：" + (CameraTriggerThread.SendDt - CameraTriggerThread.dt1).TotalMilliseconds
                            + "  GPU抓到图时间：" + CameraTriggerThread.imgDateTime.ToString("yyyy:MM:dd:HH:mm:ss:ffff")
                            + "  主界面设置信息时长：" + (dt_MainRect - dt_Set_Info).TotalMilliseconds
                            + "  画框显示时长：" + (dt_MainResult - dt_MainRect).TotalMilliseconds
                            + "  显示结果时长：" + (dt_isImageResult - dt_MainResult).TotalMilliseconds
                            + "  无日志创建日志时长：" + (dt_Txt - dt_isImageResult).TotalMilliseconds
                            + "  界面-日志时长：" + (dt_Txt - dt_Set_Info).TotalMilliseconds;
                        if ((CameraTriggerThread.dt2 - CameraTriggerThread.dt1).TotalMilliseconds < 0 || (CameraTriggerThread.dt2 - CameraTriggerThread.dt1).TotalMilliseconds > 100)
                        {
                            timeResult_ng = timeResult_ng + "  算法开始：" + CameraTriggerThread.dt1.ToString("yyyy:MM:dd:HH:mm:ss:fffff") + "  算法结束：" + CameraTriggerThread.dt2.ToString("yyyy:MM:dd:HH:mm:ss:fffff");
                        }
                        if (CameraTriggerThread.overTime != string.Empty)
                        {
                            timeResult_ng = timeResult_ng + CameraTriggerThread.overTime;
                        }
                        if (CameraTriggerThread.noImgNG != string.Empty)
                        {
                            timeResult_ng = timeResult_ng + CameraTriggerThread.noImgNG;
                        }
                        Console.WriteLine(timeResult_ng);
                        sw.WriteLine(timeResult_ng);
                        sw.Close();
                    }
                    catch (Exception eX)
                    {

                        Console.WriteLine(eX.Message);
                    }
                }

                DateTime dt_Txt_End = DateTime.Now;
                Console.WriteLine("写日志时长：" + (dt_Txt_End - dt_Txt).TotalMilliseconds);

                if (info.result == "NG")
                {
                    Console.WriteLine("GPU-NG存图");
                    try
                    {
                        //string outImgPath = Application.StartupPath + "\\out\\";
                        //string tempPath = LocalInfo.outImgPath + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "\\";
                        //if (!Directory.Exists(tempPath))
                        //{
                        //    Directory.CreateDirectory(tempPath);
                        //}
                        Console.WriteLine("存图路径: " + CreateFolderThread.currSaveImgPath);

                        if (string.IsNullOrEmpty(CreateFolderThread.currSaveImgPath) || !Directory.Exists(CreateFolderThread.currSaveImgPath))
                        {
                            CreateFolderThread.currSaveImgPath = LocalInfo.outImgPath + "\\" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm") + "\\";
                            try
                            {
                                if (!Directory.Exists(CreateFolderThread.currSaveImgPath))
                                {
                                    Directory.CreateDirectory(CreateFolderThread.currSaveImgPath);
                                    Console.WriteLine($"创建文件夹: {CreateFolderThread.currSaveImgPath}");
                                }
                            }
                            catch (Exception E)
                            {
                                Console.WriteLine($"错误: {E.Message}");
                            }
                        }
                        if (LocalInfo.isSaveNG =="1")
                        {
                            //AlgorithmModule_GPU.ConvertTo8bpp(info.Bitmap).Save(CreateFolderThread.currSaveImgPath + currTime + "_NG_" + Guid.NewGuid().ToString("N") + ".bmp");

                            info.Bitmap.Save(CreateFolderThread.currSaveImgPath + currTime + "_NG_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
                        }

                        //AlgorithmModule_GPU.RectPoints((Bitmap)mainCameraPb.Image, currPointsList).Save(CreateFolderThread.currSaveImgPath + currTime + "_NG_A_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
                        //AlgorithmModule_GPU.RectPoints((Bitmap)AlgorithmModule_GPU.RectPoints1((Bitmap)mainCameraPb.Image, currPointsList, info.wrongIndex, AlgorithmModule_GPU.mainInfos), LocalTemplateInfo.rectangle)
                        //    .Save(CreateFolderThread.currSaveImgPath + currTime + "_NG_A_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg); ;

                        mainCameraPb.Image.Save(CreateFolderThread.currSaveImgPath + currTime + "_NG_A_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg); 
                    }
                    catch (Exception eX)
                    {
                        Console.WriteLine(eX.Message);
                    }
                }
                else if (info.result == "OK")
                {
                    if (OCR_Form.oCR_Form.saveImgCb_PLC.Checked || OCR_Form.oCR_Form.saveOKImgcB.Checked)
                    {
                        //OK存图
                        Console.WriteLine("GPU-OK存图");
                        try
                        {

                            Console.WriteLine("存图路径: " + CreateFolderThread.currSaveImgPath);

                            //AlgorithmModule_GPU.ConvertTo8bpp(info.Bitmap).Save(CreateFolderThread.currSaveImgPath + currTime + "_OK_" + Guid.NewGuid().ToString("N") + ".bmp");
                            info.Bitmap.Save(CreateFolderThread.currSaveImgPath + currTime + "_OK_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);

                            //AlgorithmModule_GPU.RectPoints((Bitmap)mainCameraPb.Image, currPointsList).Save(CreateFolderThread.currSaveImgPath + currTime + "_OK_A_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
                            //AlgorithmModule_GPU.RectPoints((Bitmap)AlgorithmModule_GPU.RectPoints1((Bitmap)mainCameraPb.Image, currPointsList, info.wrongIndex, AlgorithmModule_GPU.mainInfos), LocalTemplateInfo.rectangle)
                            //.Save(CreateFolderThread.currSaveImgPath + currTime + "_OK_A_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg); ;

                            mainCameraPb.Image.Save(CreateFolderThread.currSaveImgPath + currTime + "_OK_A_" + Guid.NewGuid().ToString("N") + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg); ;

                        }
                        catch (Exception eX)
                        {
                            Console.WriteLine(eX.Message);
                        }
                    }
                }
                //label1.Text = info.DateTime.ToString("yyyy-MM-dd HH:mm:ss");
            }
        }
        private void ClearCountBtn_Click(object sender, EventArgs e)
        {
            LocalInfo.totalCount = 0;
            LocalInfo.ngCount = 0;

            LocalInfo.ProductCount_Config_InfoUpdate();
        }

        public static void OpenFolder(string folderPath)
        {
            if (!Directory.Exists(folderPath))
            {
                MessageBox.Show("路径不存在！");
                return;
            }
            try
            {
                System.Diagnostics.Process.Start("explorer.exe", folderPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打开文件夹失败: {ex.Message}");
            }
        }
        public static void OpenFile(string filePath)
        {
            if (!File.Exists(filePath))
            {
                MessageBox.Show("路径不存在！");
                return;
            }
            try
            {
                System.Diagnostics.Process.Start(filePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打开文件失败: {ex.Message}");
            }
        }
        public static void OpenFolderAndFile(string filePath, string folderPath)
        {
            if (!File.Exists(filePath) && !Directory.Exists(folderPath))
            {
                MessageBox.Show("路径不存在！");
                return;
            }
            try
            {
                System.Diagnostics.Process.Start("explorer.exe", $"/select, \"{filePath}\"");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"操作失败: {ex.Message}");
            }
        }
        private void StartPathBtn_Click(object sender, EventArgs e)
        {
            OpenFolder(Application.StartupPath);
        }

        private void LogFileBtn_Click(object sender, EventArgs e)
        {
            if (File.Exists("ImageResult.txt"))
            {
                OpenFile("ImageResult.txt");
            }

        }

        private void outImgBtn_Click(object sender, EventArgs e)
        {
            OpenFolder(LocalInfo.outImgPath);
        }

        private void ConfigFileBtn_Click(object sender, EventArgs e)
        {
            OpenFolder("Config");
        }

        private void TemplateFileBtn_Click(object sender, EventArgs e)
        {
            OpenFolder("TemplateInput");
        }

        public void HideBorder()
        {
            //this.FormBorderStyle = FormBorderStyle.None;   //无边框
            //this.ControlBox = false;   // 隐藏最大化、最小化、关闭按钮
            //this.Text = string.Empty;  // 清空标题文本
            this.MaximizeBox = true;  // 禁用最大化按钮（可选）
            this.MinimizeBox = true;  // 禁用最小化按钮（可选）

            WindowState= FormWindowState.Maximized;  //窗口最大化
            //this.TopMost = true;   //强制置顶
        }
        public List<string> GetFoldersByDate(string parentFolder, DateTime targetDate)
        {
            List<string> result = new List<string>();
            foreach (string folderPath in Directory.GetDirectories(parentFolder))
            {
                string folderName = Path.GetFileName(folderPath);
                if (DateTime.TryParseExact(folderName, "yyyy-MM-dd-HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime folderDateTime))
                {
                    if (folderDateTime.Date == targetDate.Date)
                    {
                        result.Add(folderPath);
                    }
                }
            }
            Console.WriteLine("当天时间: " + targetDate);
            Console.WriteLine("当天文件夹个数: "+result.Count);
            return result;
        }
        public List<string> GetEarliestDayFolders(string parentFolder)
        {
            string[] allFolders = Directory.GetDirectories(parentFolder);
            List<DateTime> validDates = new List<DateTime>();

            foreach (string folderPath in allFolders)
            {
                string folderName = Path.GetFileName(folderPath);
                if (DateTime.TryParseExact(folderName, "yyyy-MM-dd-HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime folderDate))
                {
                    validDates.Add(folderDate.Date);
                }
            }

            if (validDates.Count == 0) return new List<string>();

            DateTime earliestDate = validDates.Min();

            List<string> target = FilterFoldersByDate(allFolders, earliestDate, earliestDate);
            Console.WriteLine("最早时间: " + earliestDate);
            Console.WriteLine("最早一天文件夹个数: " + target.Count);
            return target;
        }

        public int GetEarliestRangeFolders(string parentFolder, int days)
        {
            string[] allFolders = Directory.GetDirectories(parentFolder);
            List<DateTime> validDates = new List<DateTime>();

            foreach (string folderPath in allFolders)
            {
                string folderName = Path.GetFileName(folderPath);
                if (DateTime.TryParseExact(folderName, "yyyy-MM-dd-HH-mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime folderDate))
                {
                    validDates.Add(folderDate.Date);
                }
            }

            if (validDates.Count == 0) return new List<string>().Count;

            DateTime startDate = validDates.Min();
            DateTime endDate = startDate.AddDays(days - 1);

            List<string> target = FilterFoldersByDate(allFolders, startDate, endDate);
            Console.WriteLine("最早时间: " + startDate + "  "+ endDate);
            Console.WriteLine("最早一天文件夹个数: " + target.Count);
            return target.Count;
        }

        private List<string> FilterFoldersByDate(string[] folders, DateTime start, DateTime end)
        {
            List<string> result = new List<string>();
            foreach (string folderPath in folders)
            {
                string folderName = Path.GetFileName(folderPath);
                if (DateTime.TryParseExact(folderName, "yyyy-MM-dd-HH-mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime folderDate))
                {
                    if (folderDate.Date >= start && folderDate.Date <= end)
                    {
                        result.Add(folderPath);
                    }
                }
            }
            return result;
        }
        private void TestDeleteImg_Click(object sender, EventArgs e)
        {
            //最远天数文件夹个数
            //int deleteCount = GetEarliestRangeFolders(LocalInfo.outImgPath, LocalInfo.deleteDay);
            //DiskSpaceManager.ProcessDeletion(LocalInfo.outImgPath, deleteCount);

            //最近天数
            DiskSpaceManager.ProcessDeletion(LocalInfo.outImgPath, LocalInfo.deleteDay);
        }

        private void DeleteDay1Rb_CheckedChanged(object sender, EventArgs e)
        {
            LocalInfo.deleteDay = 1;
        }

        private void DeleteDay3Rb_CheckedChanged(object sender, EventArgs e)
        {
            LocalInfo.deleteDay = 3;
        }

        private void StartContinuousBtn_Click(object sender, EventArgs e)
        {
            groupBox5.Enabled = false;
            SetgB.Enabled = false;
            StartBtn.Enabled = false;

            // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
            //CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerMode", "Off");
            //CameraReceiveThread.device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
            StartContinuousBtn.Enabled = false;
            CloseContinuousBtn.Enabled = true;

            //CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerSource", "Software");
            CameraReceiveRealTimeThread.iCameraReceiveRealTime_Step = 5;

            CameraTriggerThread_ModbusRealTime.iCameraTrigger_Step = 5;

        }

        private void CloseContinuousBtn_Click(object sender, EventArgs e)
        {
            groupBox5.Enabled = true;
            SetgB.Enabled = true;
            StartBtn.Enabled = true;

            //CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerMode", "On");
            //CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerSource", "Line0");
            StartContinuousBtn.Enabled = true;
            CloseContinuousBtn.Enabled = false;

            //CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerSource", "Line0");
            CameraReceiveRealTimeThread.iCameraReceiveRealTime_Step = 0;

            CameraTriggerThread_ModbusRealTime.iCameraTrigger_Step = 0;
        }

        private void SaveImgPathBtn_Click(object sender, EventArgs e)
        {
            using (var dialog = new FolderBrowserDialog())
            {
                dialog.SelectedPath = Application.StartupPath;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    LocalInfo.outImgPath = dialog.SelectedPath;
                    SaveImgPathTB.Text = LocalInfo.outImgPath;
                    LocalInfo.OutImgPath_Config_InfoUpdate();
                    //Console.WriteLine(LocalInfo.outImgPath);
                }
            }
        }



        public void SetPermissionType()
        {
            switch (LocalInfo.PermissionIndex)
            {
                case 0:
                    OpenAllGroupBox();
                    break;
                case 1:
                    CloseAllGroupBox();
                    break;
            }
        }
        public void OpenAllGroupBox()
        {
            SetgB.Enabled = true;//窗口设置
            IO_TestGB.Enabled = true;//相机调试
            SingleDelay_GB.Enabled = true;//信号延迟关闭
            ngOrOkSignal_GB.Enabled = true;//信号输出为ng或ok
            CameraSerialNumGB.Enabled = true;//相机序列号
            NGControlType_GB.Enabled = true;//是否踢料控制
            isOKRect_GB.Enabled = true;//是否ok画框

            countGB.Enabled = true;//计数
            LocalTemplateGB.Enabled = true;//本地模板信息
            FunctionSetGb.Enabled = true;//功能设置--存图--删除

        }
        public void CloseAllGroupBox()
        {
            SetgB.Enabled = false;//窗口设置
            IO_TestGB.Enabled = false;//相机调试
            SingleDelay_GB.Enabled = false;//信号延迟关闭
            ngOrOkSignal_GB.Enabled = false;//信号输出为ng或ok
            CameraSerialNumGB.Enabled = false;//相机序列号
            NGControlType_GB.Enabled = false;//是否踢料控制
            isOKRect_GB.Enabled = false;//是否ok画框

            countGB.Enabled = false;//计数
            LocalTemplateGB.Enabled = false;//本地模板信息
            FunctionSetGb.Enabled = false;//功能设置--存图--删除


        }

        private void OCR_Form_KeyDown(object sender, KeyEventArgs e)
        {
            // 判断按下的键
            //switch (e.KeyCode)
            //{
            //    case Keys.Enter:
            //        MessageBox.Show("按下了回车键 (Enter)");
            //        e.Handled = true; // 阻止事件继续传递
            //        break;
            //    case Keys.Escape:
            //        MessageBox.Show("按下了退出键 (Esc)");
            //        e.Handled = true;
            //        break;
            //    case Keys.A when e.Control: // 组合键：Ctrl + A
            //        MessageBox.Show("按下了 Ctrl + A");
            //        e.Handled = true;
            //        break;
            //}

            if (isLocalTest)
            {
                if (e.KeyCode == Keys.A)
                {
                    CloseAllGroupBox();
                    StartBtn.Hide();
                    StopBtn.Show();

                    TestSetInfoThread.TestSetInfoThread_Pause = false;
                    TestSetInfoThread.iTestSetInfo_Step = 10;

                    CreateFolderThread.CreateFolder_Pause = false;
                    CreateFolderThread.iCreateFolder_Step = 10;

                    isMainCameraPbWheel = false;

                }
                if (e.KeyCode == Keys.D)
                {
                    OpenAllGroupBox();
                    StartBtn.Show();
                    StopBtn.Hide();

                    TestSetInfoThread.iTestSetInfo_Step = 1;
                    TestSetInfoThread.TestSetInfoThread_Pause = true;

                    CreateFolderThread.iCreateFolder_Step = 1;
                    CreateFolderThread.CreateFolder_Pause = true;

                    isMainCameraPbWheel = true;
                }

                if (e.KeyCode == Keys.J)
                {
                    CameraOnlineThread.iCameraOnline_Step = 5;

                }
                if (e.KeyCode == Keys.K)
                {
                    TestSaveImg_IO2();

                }
            }

        }

        private void DeleteDayUpdown_ValueChanged(object sender, EventArgs e)
        {
            LocalInfo.deleteDay = (int)DeleteDayUpdown.Value;
            Console.WriteLine("LocalInfo.deleteDay:" + LocalInfo.deleteDay);
        }
        private void ChangeDeleteDayBtn_Click(object sender, EventArgs e)
        {
            DeleteDayUpdown.Enabled = true;
            ChangeDeleteDayBtn.Enabled = false;
            ConfirmDeleteDayBtn.Enabled = true;
        }

        private void ConfirmDeleteDayBtn_Click(object sender, EventArgs e)
        {
            try
            {
                LocalInfo.DeleteDay_Config_InfoUpdate();
                DeleteDayUpdown.Enabled = false;
                ChangeDeleteDayBtn.Enabled = true;
                ConfirmDeleteDayBtn.Enabled = false;
                MessageBox.Show("修改成功");
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }
        private void SetDeleteDay()
        {
            string path = Application.StartupPath + "\\Config\\DeleteDayConfig.json";
            DeleteDay_Config deleteDay_Config = new DeleteDay_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            deleteDay_Config = JsonMapper.ToObject<DeleteDay_Config>(re);
            LocalInfo.deleteDay = int.Parse(deleteDay_Config.DeleteDay);
            sr.Dispose();
            DeleteDayUpdown.Value = LocalInfo.deleteDay;
        }
        private void SetDI_Interval()
        {
            string path = Application.StartupPath + "\\Config\\DI_IntervalConfig.json";
            DI_Interval_Config dI_Interval = new DI_Interval_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            dI_Interval = JsonMapper.ToObject<DI_Interval_Config>(re);
            LocalInfo.DI_Interval = dI_Interval.DI_Interval;
            Console.WriteLine("LocalInfo.DI_Interval: "+ LocalInfo.DI_Interval);
            sr.Dispose();

        }
        private void SetIsLOG_Config()
        {
            string path = Application.StartupPath + "\\Config\\IsLOG_Config.json";
            isLOG_Config isLOG_Config = new isLOG_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            isLOG_Config = JsonMapper.ToObject<isLOG_Config>(re);
            LocalInfo.isLog = isLOG_Config.isLog;
            Console.WriteLine("LocalInfo.isLog: " + LocalInfo.isLog);
            sr.Dispose();
        }
        private void SetProductCount_Config()
        {
            string path = Application.StartupPath + "\\Config\\ProductCount_Config.json";
            ProductCountConfig productCountConfig = new ProductCountConfig();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            productCountConfig = JsonMapper.ToObject<ProductCountConfig>(re);
            LocalInfo.totalCount = int.Parse(productCountConfig.totalCount);
            LocalInfo.ngCount = int.Parse(productCountConfig.ngCount);
            Console.WriteLine("LocalInfo.totalCount: " + LocalInfo.totalCount);
            sr.Dispose();
        }

        private void SetTemplateImgPath_Config()
        {
            string path = Application.StartupPath + "\\Config\\TemplateImgPathConfig.json";
            TemplateImgPathConfig templateImgPathConfig = new TemplateImgPathConfig();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            templateImgPathConfig = JsonMapper.ToObject<TemplateImgPathConfig>(re);
            LocalInfo.Tem_ImgPath = templateImgPathConfig.TemplateImgPath;
            Console.WriteLine("LocalInfo.Tem_ImgPath: " + LocalInfo.Tem_ImgPath);
            sr.Dispose();
        }
        private void SetTem_RectMaxCount_Config()
        {
            string path = Application.StartupPath + "\\Config\\Tem_RectMaxCount_Config.json";
            Tem_RectMaxCount_Config tem_RectMaxCount_Config = new Tem_RectMaxCount_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            tem_RectMaxCount_Config = JsonMapper.ToObject<Tem_RectMaxCount_Config>(re);
            LocalInfo.Tem_RectMaxCount = int.Parse(tem_RectMaxCount_Config.Tem_RectMaxCount);
            Console.WriteLine("LocalInfo.Tem_RectMaxCount: " + LocalInfo.Tem_RectMaxCount);
            sr.Dispose();
        }

        public static void SetLocalTemplateInfos()
        {
            //oCR_Form.LocalTemplateInfoTB01.Text = LocalTemplateInfo.Info01;
            //oCR_Form.LocalTemplateInfoTB02.Text = LocalTemplateInfo.Info02;
            //oCR_Form.LocalTemplateInfoTB03.Text = LocalTemplateInfo.Info03;
            //oCR_Form.LocalTemplateInfoTB04.Text = LocalTemplateInfo.Info04;
            //oCR_Form.LocalTemplateInfoTB05.Text = LocalTemplateInfo.Info05;
            //oCR_Form.LocalTemplateInfoTB06.Text = LocalTemplateInfo.Info06;
            oCR_Form.LocalTemplateInfoTB01.Text = oCR_Form.LocalTemplateInfoTB02.Text
                = oCR_Form.LocalTemplateInfoTB03.Text = oCR_Form.LocalTemplateInfoTB04.Text
                = oCR_Form.LocalTemplateInfoTB05.Text = oCR_Form.LocalTemplateInfoTB06.Text = string.Empty;

            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList.Count >= 1)
                oCR_Form.LocalTemplateInfoTB01.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList[0];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList.Count >= 2)
                oCR_Form.LocalTemplateInfoTB02.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList[1];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList.Count >= 3)
                oCR_Form.LocalTemplateInfoTB03.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList[2];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList.Count >= 4)
                oCR_Form.LocalTemplateInfoTB04.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList[3];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList.Count >= 5)
                oCR_Form.LocalTemplateInfoTB05.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList[4];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList.Count >= 6)
                oCR_Form.LocalTemplateInfoTB06.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[0].InfoList[5];
        }

        private void LocalTemplateChangeBtn_Click(object sender, EventArgs e)
        {
            LocalTemplateInfoTB01.Enabled = true;
            LocalTemplateInfoTB02.Enabled = true;
            LocalTemplateInfoTB03.Enabled = true;
            LocalTemplateInfoTB04.Enabled = true;
            LocalTemplateInfoTB05.Enabled = true;
            LocalTemplateInfoTB06.Enabled = true;

            templateInfoLastBtn.Enabled = false;
            templateInfoNextBtn.Enabled = false;

            UnifiedTemCB.Enabled = false;

            LocalTemplateChangeBtn.Enabled = false;
            LocalTemplateConfirmBtn.Enabled = true;
        }
        public static List<string> LocalTemplateInfoList = new List<string>();
        private void LocalTemplateConfirmBtn_Click(object sender, EventArgs e)
        {
            try
            {
                LocalTemplateInfoList.Clear();
                if (LocalTemplateInfoTB01.Text != string.Empty)
                    LocalTemplateInfoList.Add(LocalTemplateInfoTB01.Text);
                if (LocalTemplateInfoTB02.Text != string.Empty)
                    LocalTemplateInfoList.Add(LocalTemplateInfoTB02.Text);
                if (LocalTemplateInfoTB03.Text != string.Empty)
                    LocalTemplateInfoList.Add(LocalTemplateInfoTB03.Text);
                if (LocalTemplateInfoTB04.Text != string.Empty)
                    LocalTemplateInfoList.Add(LocalTemplateInfoTB04.Text);
                if (LocalTemplateInfoTB05.Text != string.Empty)
                    LocalTemplateInfoList.Add(LocalTemplateInfoTB05.Text);
                if (LocalTemplateInfoTB06.Text != string.Empty)
                    LocalTemplateInfoList.Add(LocalTemplateInfoTB06.Text);

                if (UnifiedTemCB.Checked)
                {
                    for (int i = 0; i < LocalTemplateSingleInfos_Config.localTemplateSingleInfos.Count; i++)
                    {
                        LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList = LocalTemplateInfoList;
                    }
                }
                else
                {
                    LocalTemplateSingleInfos_Config.localTemplateSingleInfos[currLocalTemplateInfoIndex].InfoList = LocalTemplateInfoList;
                }

                LocalTemplateSingleInfos_Config.LocalTemplateInfoSave(LocalTemplateSingleInfos_Config.localTemplateSingleInfos);
                LocalTemplateSingleInfos_Config.LocalTemplateSingleInfosInitial();

                if (isConfigList)
                {
                    LocalTemplateList_Config.LocalTemplateList.LocalTemplateSingleInfos = LocalTemplateSingleInfos_Config.localTemplateSingleInfos;
                    LocalTemplateList_Config.LocalTemplateInfoSave(LocalTemplateList_Config.LocalTemplateList);
                    LocalTemplateList_Config.LocalTemplateSingleInfosInitial(LocalInfo.ProductConfigListName);
                }
   

                MessageBox.Show("本地模板修改成功");

                LocalTemplateInfoTB01.Enabled = false;
                LocalTemplateInfoTB02.Enabled = false;
                LocalTemplateInfoTB03.Enabled = false;
                LocalTemplateInfoTB04.Enabled = false;
                LocalTemplateInfoTB05.Enabled = false;
                LocalTemplateInfoTB06.Enabled = false;

                templateInfoLastBtn.Enabled = true;
                templateInfoNextBtn.Enabled = true;
                UnifiedTemCB.Enabled = true;

                LocalTemplateChangeBtn.Enabled = true;
                LocalTemplateConfirmBtn.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        public static int currLocalTemplateInfoIndex;
        public void SetLocalTemplateInfoPanel()
        {
            if(Image.FromFile("Resources\\Last.png") != null)
                templateInfoLastBtn.Image = Image.FromFile("Resources\\Last.png");
            if (Image.FromFile("Resources\\Next.png") != null)
                templateInfoNextBtn.Image = Image.FromFile("Resources\\Next.png");

            LocalTemplateInfoLabel.Text = "模板1";

            currLocalTemplateInfoIndex = 0;
        }

        private void templateInfoLastBtn_Click(object sender, EventArgs e)
        {
            currLocalTemplateInfoIndex = (currLocalTemplateInfoIndex - 1 + LocalInfo.Tem_RectMaxCount) % LocalInfo.Tem_RectMaxCount;
            Console.WriteLine("currLocalTemplateInfoIndex: "+ currLocalTemplateInfoIndex);
            //if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[currLocalTemplateInfoIndex].InfoList.Count <= 0)
            //    return;
            LocalTemplateInfoLabel.Text = "模板"+(currLocalTemplateInfoIndex+1).ToString();
            SetLocalTemplateInfos(currLocalTemplateInfoIndex);
        }

        private void templateInfoNextBtn_Click(object sender, EventArgs e)
        {
            currLocalTemplateInfoIndex = (currLocalTemplateInfoIndex + 1) % LocalInfo.Tem_RectMaxCount;
            Console.WriteLine("currLocalTemplateInfoIndex: " + currLocalTemplateInfoIndex);
            //if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[currLocalTemplateInfoIndex].InfoList.Count <= 0)
            //    return;
            LocalTemplateInfoLabel.Text = "模板" + (currLocalTemplateInfoIndex + 1).ToString();
            SetLocalTemplateInfos(currLocalTemplateInfoIndex);
        }
        public static void SetLocalTemplateInfos(int index)
        {


            oCR_Form.LocalTemplateInfoTB01.Text = oCR_Form.LocalTemplateInfoTB02.Text
                = oCR_Form.LocalTemplateInfoTB03.Text = oCR_Form.LocalTemplateInfoTB04.Text
                = oCR_Form.LocalTemplateInfoTB05.Text = oCR_Form.LocalTemplateInfoTB06.Text = string.Empty;

            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList.Count >= 1)
                oCR_Form.LocalTemplateInfoTB01.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList[0];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList.Count >= 2)
                oCR_Form.LocalTemplateInfoTB02.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList[1];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList.Count >= 3)
                oCR_Form.LocalTemplateInfoTB03.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList[2];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList.Count >= 4)
                oCR_Form.LocalTemplateInfoTB04.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList[3];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList.Count >= 5)
                oCR_Form.LocalTemplateInfoTB05.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList[4];
            if (LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList.Count >= 6)
                oCR_Form.LocalTemplateInfoTB06.Text = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[index].InfoList[5];
        }

        private void SetCameraSerialNumber_Config()
        {
            string path = Application.StartupPath + "\\Config\\CameraSerialNumber_Config.json"; 
             CameraSerialNumber_Config cameraSerialNumber_Config = new CameraSerialNumber_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            cameraSerialNumber_Config = JsonMapper.ToObject<CameraSerialNumber_Config>(re);
            LocalInfo.CameraSerialNumber = cameraSerialNumber_Config.CameraSerialNumber;
            Console.WriteLine("LocalInfo.CameraSerialNumber:" + LocalInfo.CameraSerialNumber);
            sr.Dispose();


            //检测授权
            //string path_authorization = "Config\\Authorization_Config.txt";
            //if (!File.Exists(path_authorization))
            //{
            //    LocalInfo.isAuthorization = false;
            //    MessageBox.Show("未找到授权文件！");
            //}
            //else
            //{
            //    StreamReader sr1 = new StreamReader(path_authorization);
            //    string re1 = sr1.ReadToEnd();

            //    string cameraSernum = DecryptPublicKeyJava1(LocalInfo.PublicKey, re1);
            //    sr1.Dispose();

            //    if (cameraSernum == LocalInfo.CameraSerialNumber)
            //    {
            //        LocalInfo.isAuthorization = true;
            //    }
            //    else
            //    {
            //        LocalInfo.isAuthorization = false;
            //        MessageBox.Show("设备未授权！");
            //    }
            //}


        }

        public void SetCameraSerialNumGB()
        {
            SerialNumTB.Text = LocalInfo.CameraSerialNumber;
        }

        private void ChangeSerialNumBtn_Click(object sender, EventArgs e)
        {
            if (CameraReceiveThread.isGrabbing)
            {
                //MessageBox.Show("已有相机连接中");
                CameraReceiveThread.CloseDevice();
                //return;
            }
            SerialNumTB.Enabled = true;

            ChangeSerialNumBtn.Enabled = false;
            ConfirmSerialNumBtn.Enabled = true;
        }

        private void ConfirmSerialNumBtn_Click(object sender, EventArgs e)
        {
            try
            {
                LocalInfo.CameraSerialNumber = SerialNumTB.Text;
                LocalInfo.CameraSerialNumber_Config_InfoUpdate();
                SerialNumTB.Enabled = false;
                ChangeSerialNumBtn.Enabled = true;
                ConfirmSerialNumBtn.Enabled = false;
                MessageBox.Show("修改成功");

                CameraReceiveThread.RefreshDeviceList();


            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }


        public static void AppendLog(string message, bool isError = false, bool isSuccess = false)
        {
            var txtLog = OCR_Form.oCR_Form.richTB_State_PLC;
            OCR_Form.oCR_Form.BeginInvoke(new Action(() =>
            {
                string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
                Color color = Color.Silver;

                if (isError) color = Color.Red;//Color.OrangeRed   Color.Silver
                else if (isSuccess) color = Color.LimeGreen;//Color.LimeGreen

                txtLog.SelectionStart = txtLog.TextLength;
                txtLog.SelectionColor = color;
                txtLog.AppendText($"[{timestamp}] {message}\n");
                txtLog.ScrollToCaret();
            }));
        }


        public static string DecryptPublicKeyJava(string publicKeyJava, string encryptedData, string encoding = "UTF-8")
        {
            // 处理Base64数据补位
            while (encryptedData.Length % 4 != 0)
            {
                encryptedData += "=";
            }

            // 创建RSA参数
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory
                .CreateKey(Convert.FromBase64String(publicKeyJava));//Convert.FromBase64String(publicKeyJava)

            // 初始化RSA引擎
            var rsaEngine = new RsaEngine();
            rsaEngine.Init(false, publicKeyParam); // false表示解密模式

            // 执行解密
            byte[] dataBytes = Convert.FromBase64String(encryptedData);
            byte[] resultBytes = rsaEngine.ProcessBlock(dataBytes, 0, dataBytes.Length);

            return Encoding.UTF8.GetString(resultBytes);
        }


        public static string DecryptPublicKeyJava1(string publicKeyJava, string data, string encoding = "UTF-8")
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKeyJava));

            //判断data是否是4的倍数，不是的话后面加=号，再接着判断，直到是4的倍数
            data = IsMultipleOfFour(data);

            byte[] cipherbytes = Convert.FromBase64String(data);
            RsaEngine rsa = new RsaEngine();
            rsa.Init(false, publicKeyParam);//参数true表示加密/false表示解密。
            cipherbytes = rsa.ProcessBlock(cipherbytes, 0, cipherbytes.Length);

            string decryptStr = Encoding.GetEncoding(encoding).GetString(cipherbytes).ToString();
            decryptStr = Regex.Replace(decryptStr, @"[^\u0000-\u007F]", string.Empty);
            decryptStr = decryptStr.Replace("\x01", "");
            Console.WriteLine("decryptStr:" + decryptStr.Substring(1));
            return decryptStr.Substring(1);
        }

        public static string IsMultipleOfFour(string str)
        {
            int _cnt = 0;
            while (str.Length % 4 != 0)
            {
                _cnt++;
                if (_cnt > 10)
                {
                    return str;
                }
                str += "=";
            }
            return str.ToString();
        }
        public void SetNgOrOkSignal()
        {
            string path = Application.StartupPath + "\\Config\\NgOrOkSignal_Config.json";
            NgOrOkSignal_Config ngOrOkSignal_Config = new NgOrOkSignal_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            ngOrOkSignal_Config = JsonMapper.ToObject<NgOrOkSignal_Config>(re);
            LocalInfo.ngOrOkSignal = ngOrOkSignal_Config.NgOrOkSignal;
            Console.WriteLine("LocalInfo.ngOrOkSignal:" + LocalInfo.ngOrOkSignal);
            sr.Dispose();

            if(LocalInfo.ngOrOkSignal == "0")
            {
                ngRB.Checked = true;
            }
            else if (LocalInfo.ngOrOkSignal == "1")
            {
                okRB.Checked = true;
            }
        }

        public void SetIsStartRunConfig()
        {
            string path = Application.StartupPath + "\\Config\\IsStartRun_Config.json";
            IsStartRun_Config isStartRun_Config = new IsStartRun_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            isStartRun_Config = JsonMapper.ToObject<IsStartRun_Config>(re);
            LocalInfo.isStartRun = isStartRun_Config.isStartRun;
            Console.WriteLine("LocalInfo.isStartRun:" + LocalInfo.isStartRun);
            sr.Dispose();

        }

        private void ngRB_CheckedChanged(object sender, EventArgs e)
        {
            if (ngRB.Checked)
            {
                LocalInfo.ngOrOkSignal = "0";

            }
            else
            {
                LocalInfo.ngOrOkSignal = "1";
            }
            LocalInfo.NgOrOkSignal_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.ngOrOkSignal:  " + LocalInfo.ngOrOkSignal);
        }

        public void SetCloseSignalDelayTime_Config()
        {
            string path = Application.StartupPath + "\\Config\\CloseSignalDelayTime_Config.json";
            CloseSignalDelayTime_Config closeSignalDelayTime = new CloseSignalDelayTime_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            closeSignalDelayTime = JsonMapper.ToObject<CloseSignalDelayTime_Config>(re);
            LocalInfo.CloseSignalDelayTime = closeSignalDelayTime.CloseSignalDelayTime;
            Console.WriteLine("LocalInfo.CloseSignalDelayTime:" + LocalInfo.CloseSignalDelayTime);
            sr.Dispose();

            CloseSignalDelayTimeTb.Text = LocalInfo.CloseSignalDelayTime;
        }
        private void ChangeDelayTimeBtn_Click(object sender, EventArgs e)
        {
            ChangeDelayTimeBtn.Enabled = false;
            ConfirmDelayTimeBtn.Enabled = true;
            CloseSignalDelayTimeTb.Enabled = true;

        }

        private void ConfirmDelayTimeBtn_Click(object sender, EventArgs e)
        {
            ChangeDelayTimeBtn.Enabled = true;
            ConfirmDelayTimeBtn.Enabled = false;
            CloseSignalDelayTimeTb.Enabled = false;

            if(int.TryParse(CloseSignalDelayTimeTb.Text, out int num))
            {
                if(num >= 30 && num <= 500)
                {
                    LocalInfo.CloseSignalDelayTime = num.ToString();
                    LocalInfo.CloseSignalDelayTime_Config_InfoUpdate();
                    MessageBox.Show("设置成功！");
                }
                else
                {
                    MessageBox.Show("请在30~500范围内设置！");
                    SetCloseSignalDelayTime_Config();
                }
            }
            else
            {
                MessageBox.Show("请输入正确的格式！");
                SetCloseSignalDelayTime_Config();
            }
        }
        public static bool IsValidIntInRange(string input, int min, int max)
        {
            if (int.TryParse(input, out int number))
            {
                return number >= min && number <= max;
            }
            return false;
        }
        private const long MaxFileSize = 1024 * 1024 * 500; // 1MB文件大小限制
        public static void ProcessFile(string filePath)
        {
            try
            {
                // 检查文件是否存在
                if (!File.Exists(filePath))
                {
                    File.Create(filePath).Close();
                    Console.WriteLine("文件已创建: " + filePath);
                    return;
                }

                // 获取文件信息
                FileInfo fileInfo = new FileInfo(filePath);

                // 检查文件大小
                if (fileInfo.Length > MaxFileSize)
                {
                    string newFileName = GenerateBackupName(filePath);
                    File.Move(filePath, "ImageResultFiles/" + newFileName);
                    File.Create(filePath).Close();
                    Console.WriteLine($"文件过大，已备份为: {newFileName}");
                }
                else
                {
                    Console.WriteLine("文件大小正常: " + filePath);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("处理文件时出错: " + ex.Message);
            }
        }

        private static string GenerateBackupName(string originalPath)
        {
            string dir = Path.GetDirectoryName(originalPath);
            string fileName = Path.GetFileNameWithoutExtension(originalPath);
            string ext = Path.GetExtension(originalPath);
            string timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");

            return Path.Combine(dir, $"{fileName}_{timestamp}{ext}");
        }

        public static long GetFolderSize(string folderPath)
        {
            if (!Directory.Exists(folderPath))
                throw new DirectoryNotFoundException($"目录不存在: {folderPath}");

            DirectoryInfo dirInfo = new DirectoryInfo(folderPath);
            return CalculateSize(dirInfo);
        }

        private static long CalculateSize(DirectoryInfo directory)
        {
            long size = 0;

            // 计算当前目录下所有文件大小
            FileInfo[] files = directory.GetFiles();
            size += files.Sum(file => file.Length);

            // 递归计算子目录大小
            DirectoryInfo[] subDirs = directory.GetDirectories();
            foreach (DirectoryInfo subDir in subDirs)
            {
                size += CalculateSize(subDir);
            }

            return size;
        }
        public static string FormatSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            int order = 0;
            while (bytes >= 1024 && order < sizes.Length - 1)
            {
                order++;
                bytes /= 1024;
            }
            return $"{bytes:0.##} {sizes[order]}";
        }


        public void SetNGControlType_Config()
        {
            string path = Application.StartupPath + "\\Config\\NGControlType_Config.json";
            NGControlType_Config nGControlType_Config = new NGControlType_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            nGControlType_Config = JsonMapper.ToObject<NGControlType_Config>(re);
            LocalInfo.NGControlType = nGControlType_Config.NGControlType;
            Console.WriteLine("LocalInfo.NGControlType:" + LocalInfo.NGControlType);
            sr.Dispose();
            if (LocalInfo.NGControlType == "0")
            {
                ControlNG_RB.Checked = true;
                NoControlNG_RB.Checked = false;
            }
            else if (LocalInfo.NGControlType == "1")
            {
                ControlNG_RB.Checked = false;
                NoControlNG_RB.Checked = true;
            }
            //CloseSignalDelayTimeTb.Text = LocalInfo.CloseSignalDelayTime;
        }
        public void SetRepeatSignalCheckTime_Config()
        {
            string path = Application.StartupPath + "\\Config\\RepeatSignalCheckTime_Config.json";
            RepeatSignalCheckTime_Config repeatSignalCheckTime_Config = new RepeatSignalCheckTime_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            repeatSignalCheckTime_Config = JsonMapper.ToObject<RepeatSignalCheckTime_Config>(re);
            LocalInfo.RepeatSignalCheckTime = repeatSignalCheckTime_Config.RepeatSignalCheckTime;
            Console.WriteLine("LocalInfo.RepeatSignalCheckTime:" + LocalInfo.RepeatSignalCheckTime);
            sr.Dispose();

            //CloseSignalDelayTimeTb.Text = LocalInfo.CloseSignalDelayTime;
        }
        public void SetisOKRect_Config()
        {
            string path = Application.StartupPath + "\\Config\\isOKRect_Config.json";
            isOKRect_Config isOKRect_Config = new isOKRect_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            isOKRect_Config = JsonMapper.ToObject<isOKRect_Config>(re);
            LocalInfo.isOKRect = isOKRect_Config.isOKRect;
            Console.WriteLine("LocalInfo.isOKRect:" + LocalInfo.isOKRect);
            sr.Dispose();

            if (LocalInfo.isOKRect == "0")
            {
                OKRect_OPEN_RB.Checked = false;
                OKRect_CLOSE_RB.Checked = true;
            }
            else if (LocalInfo.isOKRect == "1")
            {
                OKRect_OPEN_RB.Checked = true;
                OKRect_CLOSE_RB.Checked = false;
            }
        }

        public void SetCheckDI_Config()
        {
            string path = Application.StartupPath + "\\Config\\CheckDI_Config.json";
            CheckDI_Config checkDI_Config = new CheckDI_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            checkDI_Config = JsonMapper.ToObject<CheckDI_Config>(re);
            LocalInfo.CheckDI = checkDI_Config.CheckDI;
            Console.WriteLine("LocalInfo.CheckDI:" + LocalInfo.CheckDI);
            sr.Dispose();

            //if (LocalInfo.isOKRect == "0")
            //{
            //    OKRect_OPEN_RB.Checked = false;
            //    OKRect_CLOSE_RB.Checked = true;
            //}
            //else if (LocalInfo.isOKRect == "1")
            //{
            //    OKRect_OPEN_RB.Checked = true;
            //    OKRect_CLOSE_RB.Checked = false;
            //}
        }
        public void SetisSaveOK_Config()
        {
            string path = Application.StartupPath + "\\Config\\isSaveOK_Config.json";
            isSaveOK_Config isSaveOK_Config = new isSaveOK_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            isSaveOK_Config = JsonMapper.ToObject<isSaveOK_Config>(re);
            LocalInfo.isSaveOK = isSaveOK_Config.isSaveOK;
            Console.WriteLine("LocalInfo.isSaveOK:" + LocalInfo.isSaveOK);
            sr.Dispose();//saveImgcB

            if (LocalInfo.isSaveOK == "0")
            {
                saveOKImgcB.Checked = false;
            }
            else if (LocalInfo.isSaveOK == "1")
            {
                saveOKImgcB.Checked = true;
            }
        }

        public void SetisSaveNG_Config()
        {
            string path = Application.StartupPath + "\\Config\\isSaveNG_Config.json";
            isSaveNG_Config isSaveNG_Config = new isSaveNG_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            isSaveNG_Config = JsonMapper.ToObject<isSaveNG_Config>(re);
            LocalInfo.isSaveNG = isSaveNG_Config.isSaveNG;
            Console.WriteLine("LocalInfo.isSaveNG:" + LocalInfo.isSaveNG);
            sr.Dispose();//saveImgcB

            if (LocalInfo.isSaveNG == "0")
            {
                saveNGImgcB.Checked = false;
            }
            else if (LocalInfo.isSaveNG == "1")
            {
                saveNGImgcB.Checked = true;
            }
        }

        /// <summary>
        /// 读取产品配置清单
        /// </summary>
        private void SetProductConfigListName_Config()
        {
            string path = Application.StartupPath + "\\Config\\ProductConfigListName_Config.json";
            ProductConfigListName_Config ProductConfigListName_Config = new ProductConfigListName_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            ProductConfigListName_Config = JsonMapper.ToObject<ProductConfigListName_Config>(re);
            LocalInfo.ProductConfigListName = ProductConfigListName_Config.ProductConfigListName;
            Console.WriteLine("LocalInfo.ProductConfigListName: " + LocalInfo.ProductConfigListName);
            sr.Dispose();
        }
        private void ControlNG_RB_CheckedChanged(object sender, EventArgs e)
        {
            if (ControlNG_RB.Checked)
            {
                LocalInfo.NGControlType = "0";

            }
            else
            {
                LocalInfo.NGControlType = "1";
            }
            LocalInfo.NGControlType_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.NGControlType:  " + LocalInfo.NGControlType);
        }

        private void NoControlNG_RB_CheckedChanged(object sender, EventArgs e)
        {
            if (NoControlNG_RB.Checked)
            {
                LocalInfo.NGControlType = "1";

            }
            else
            {
                LocalInfo.NGControlType = "0";
            }
            LocalInfo.NGControlType_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.NGControlType:  " + LocalInfo.NGControlType);
        }

        private void OKRect_OPEN_RB_CheckedChanged(object sender, EventArgs e)
        {
            if (OKRect_OPEN_RB.Checked)
            {
                LocalInfo.isOKRect = "1";

            }
            else
            {
                LocalInfo.isOKRect = "0";
            }
            LocalInfo.isOKRect_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.isOKRect:  " + LocalInfo.isOKRect);
        }

        private void OKRect_CLOSE_RB_CheckedChanged(object sender, EventArgs e)
        {
            if (OKRect_CLOSE_RB.Checked)
            {
                LocalInfo.isOKRect = "0";

            }
            else
            {
                LocalInfo.isOKRect = "1";
            }
            LocalInfo.isOKRect_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.isOKRect:  " + LocalInfo.isOKRect);
        }

        private void CameraSingleTriBtn_Click(object sender, EventArgs e)
        {
            if (!CameraReceiveThread.isGrabbing)
            {
                MessageBox.Show("相机未连接");
                return;
            }
            CameraSingleTriggerThread.iCameraSingleTrigger_Step = 20;
        }

        private void mainCameraPb_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                ReturnManiCameraPb();
            }
        }

        public static void LightStateDo(int state)
        {
            switch (state)
            {
                case 7://启动
                    Console.WriteLine("----启动状态----");
                    IOThread_Run.DO_Trigger_olng(7, 1);
                    IOThread_Run.DO_Trigger_olng(8, 0);
                    IOThread_Run.DO_Trigger_olng(9, 0);
                    break;
                case 8://停止
                    Console.WriteLine("----停止状态----");
                    IOThread_Run.DO_Trigger_olng(7, 0);
                    IOThread_Run.DO_Trigger_olng(8, 1);
                    IOThread_Run.DO_Trigger_olng(9, 0);
                    break;
                case 9://报警
                    Console.WriteLine("----报警状态----");
                    //IOThread_Run.DO_Trigger_olng(7, 0);
                    //IOThread_Run.DO_Trigger_olng(8, 0);
                    IOThread_Run.DO_Trigger_olng(9, 1);
                    break;
            }
        }

        public static List<Rectangle> ConvertToRectangles(List<List<System.Drawing.Point>> pointLists)
        {
            return pointLists.Select(points =>
            {
                if (points.Count < 4)
                    throw new ArgumentException("每个点列表需包含至少4个顶点");
                int minX = points.Min(p => p.X);
                int minY = points.Min(p => p.Y);
                int maxX = points.Max(p => p.X);
                int maxY = points.Max(p => p.Y);
                return new Rectangle(minX, minY, maxX - minX, maxY - minY);
            }).ToList();
        }

        public static List<List<System.Drawing.Point>> ConvertToPointLists(List<Rectangle> rectangles)
        {
            return rectangles.Select(rect => new List<System.Drawing.Point>
    {
        new System.Drawing.Point(rect.X, rect.Y),                     // 左上
        new System.Drawing.Point(rect.X + rect.Width, rect.Y),        // 右上
        new System.Drawing.Point(rect.X + rect.Width, rect.Y + rect.Height), // 右下
        new System.Drawing.Point(rect.X, rect.Y + rect.Height)        // 左下
    }).ToList();
        }

        private void saveNGImgcB_CheckedChanged(object sender, EventArgs e)
        {
            if (saveNGImgcB.Checked)
            {
                LocalInfo.isSaveNG = "1";

            }
            else
            {
                LocalInfo.isSaveNG = "0";
            }
            LocalInfo.isSaveNG_Config_InfoUpdate();
            Console.WriteLine("LocalInfo.isSaveNG:  " + LocalInfo.isSaveNG);
        }


        #region DoublePressHotkey
        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);

        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        private const int SW_RESTORE = 9;

        // Windows API常量
        private const int WM_HOTKEY = 0x0312;
        private const int MOD_CONTROL = 0x0002;

        // 热键ID
        private const int HOTKEY_ID_1 = 1;
        private const int HOTKEY_ID_2 = 2;

        // 双击检测相关变量
        private int ctrl1PressCount = 0;
        private int ctrl2PressCount = 0;
        private System.Timers.Timer ctrl1Timer;
        private System.Timers.Timer ctrl2Timer;
        private const double DOUBLE_PRESS_INTERVAL = 500; // 双击间隔500毫秒

        private void InitializeTimers()
        {
            // 初始化Ctrl+1双击检测定时器
            ctrl1Timer = new System.Timers.Timer(DOUBLE_PRESS_INTERVAL);
            ctrl1Timer.Elapsed += OnCtrl1TimerElapsed;
            ctrl1Timer.AutoReset = false;

            // 初始化Ctrl+2双击检测定时器
            ctrl2Timer = new System.Timers.Timer(DOUBLE_PRESS_INTERVAL);
            ctrl2Timer.Elapsed += OnCtrl2TimerElapsed;
            ctrl2Timer.AutoReset = false;
        }

        private void RegisterHotKeys()
        {
            // 注册Ctrl+1热键
            if (!RegisterHotKey(this.Handle, HOTKEY_ID_1, MOD_CONTROL, (int)Keys.D1))
            {
                MessageBox.Show("无法注册Ctrl+1热键", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // 注册Ctrl+2热键
            if (!RegisterHotKey(this.Handle, HOTKEY_ID_2, MOD_CONTROL, (int)Keys.D2))
            {
                MessageBox.Show("无法注册Ctrl+2热键", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            Console.WriteLine("热键已注册：双击Ctrl+1(切换本程序) 双击Ctrl+2(切换火狐)");
            Console.WriteLine("按键计数：Ctrl+1: 0次, Ctrl+2: 0次");

            //lblStatus.Text = "热键已注册：双击Ctrl+1(切换本程序) 双击Ctrl+2(切换火狐)";
            //lblPressCount.Text = "按键计数：Ctrl+1: 0次, Ctrl+2: 0次";
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_HOTKEY)
            {
                int id = m.WParam.ToInt32();

                switch (id)
                {
                    case HOTKEY_ID_1:
                        HandleCtrl1Press();
                        break;
                    case HOTKEY_ID_2:
                        HandleCtrl2Press();
                        break;
                }
            }

            base.WndProc(ref m);
        }

        private void HandleCtrl1Press()
        {
            ctrl1PressCount++;
            UpdatePressCountDisplay();

            // 如果是第一次按键，启动定时器
            if (ctrl1PressCount == 1)
            {
                ctrl1Timer.Start();
                Console.WriteLine($"检测到Ctrl+1按键 ({ctrl1PressCount}/2) - {DateTime.Now:HH:mm:ss}");
                //lblStatus.Text = $"检测到Ctrl+1按键 ({ctrl1PressCount}/2) - {DateTime.Now:HH:mm:ss}";
            }
            // 如果是第二次按键且在定时器有效期内
            else if (ctrl1PressCount == 2 && ctrl1Timer.Enabled)
            {
                ctrl1Timer.Stop();
                SwitchToFirefox();
                ResetCtrl1Count();
            }
        }

        private void HandleCtrl2Press()
        {
            ctrl2PressCount++;
            UpdatePressCountDisplay();

            // 如果是第一次按键，启动定时器
            if (ctrl2PressCount == 1)
            {
                ctrl2Timer.Start();
                Console.WriteLine($"检测到Ctrl+2按键 ({ctrl2PressCount}/2) - {DateTime.Now:HH:mm:ss}");
                //lblStatus.Text = $"检测到Ctrl+2按键 ({ctrl2PressCount}/2) - {DateTime.Now:HH:mm:ss}";
            }
            // 如果是第二次按键且在定时器有效期内
            else if (ctrl2PressCount == 2 && ctrl2Timer.Enabled)
            {
                ctrl2Timer.Stop();
                SwitchToCurrentApp();
                ResetCtrl2Count();
            }
        }

        private void OnCtrl1TimerElapsed(object sender, ElapsedEventArgs e)
        {
            // 定时器到期，重置计数（需要在UI线程中执行）
            this.Invoke(new Action(() =>
            {
                ResetCtrl1Count();
                Console.WriteLine("Ctrl+1双击超时，已重置计数");
                //lblStatus.Text = "Ctrl+1双击超时，已重置计数";
            }));
        }

        private void OnCtrl2TimerElapsed(object sender, ElapsedEventArgs e)
        {
            // 定时器到期，重置计数（需要在UI线程中执行）
            this.Invoke(new Action(() =>
            {
                ResetCtrl2Count();
                Console.WriteLine("Ctrl+2双击超时，已重置计数");
                //lblStatus.Text = "Ctrl+2双击超时，已重置计数";
            }));
        }

        private void ResetCtrl1Count()
        {
            ctrl1PressCount = 0;
            UpdatePressCountDisplay();
        }

        private void ResetCtrl2Count()
        {
            ctrl2PressCount = 0;
            UpdatePressCountDisplay();
        }

        private void UpdatePressCountDisplay()
        {
            Console.WriteLine($"按键计数：Ctrl+1: {ctrl1PressCount}次, Ctrl+2: {ctrl2PressCount}次");
            //lblPressCount.Text = $"按键计数：Ctrl+1: {ctrl1PressCount}次, Ctrl+2: {ctrl2PressCount}次";
        }

        private void SwitchToCurrentApp()
        {
            this.Activate();
            this.WindowState = FormWindowState.Normal;
            this.BringToFront();

            // 更新状态显示
            Console.WriteLine($"已双击切换到本程序 - {DateTime.Now:HH:mm:ss}");
            //lblStatus.Text = $"已双击切换到本程序 - {DateTime.Now:HH:mm:ss}";
        }

        private void SwitchToFirefox()
        {
            // 获取所有火狐浏览器进程
            Process[] firefoxProcesses = Process.GetProcessesByName("firefox");

            if (firefoxProcesses.Length > 0)
            {
                // 火狐已打开，切换到现有窗口
                foreach (Process process in firefoxProcesses)
                {
                    try
                    {
                        if (process.MainWindowHandle != IntPtr.Zero)
                        {
                            // 恢复窗口（如果最小化）
                            ShowWindow(process.MainWindowHandle, SW_RESTORE);
                            SetForegroundWindow(process.MainWindowHandle);

                            Console.WriteLine($"已双击切换到火狐浏览器 - {DateTime.Now:HH:mm:ss}");
                            //lblStatus.Text = $"已双击切换到火狐浏览器 - {DateTime.Now:HH:mm:ss}";
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        // 忽略无法访问的进程
                        continue;
                    }
                }
                MessageBox.Show("火狐浏览器正在运行但没有主窗口");
                //lblStatus.Text = "火狐浏览器正在运行但没有主窗口";
            }
            else
            {
                Console.WriteLine("火狐浏览器未运行");
                MessageBox.Show("火狐浏览器未运行");
                try
                {
                    Process.Start("firefox.exe");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Failed to start Firefox: {ex.Message}");
                }

                //lblStatus.Text = "火狐浏览器未运行";
            }
        }
        #endregion
    }
}


